Defining Classes
Navigate Classes and Objects topic: ) |
Fundamentals
editEvery class in Java can be composed of the following elements:
- fields, member variables or instance variables — Fields are variables that hold data specific to each object. For example, an employee might have an ID number. There is one field for each object of a class.
- member methods or instance methods — Member methods perform operations on an object. For example, an employee might have a method to issue his paycheck or to access his name.
- static fields or class fields — Static fields are common to any object of the same class. For example, a static field within the Employee class could keep track of the last ID number issued. Each static field exists only once in the class, regardless of how many objects are created for that class.
- static methods or class methods — Static methods are methods that do not affect a specific object.
- inner classes — Sometimes it is useful to contain a class within another one if it is useless outside of the class or should not be accessed outside the class.
- Constructors — A special method that generates a new object.
- Parameterized types — Since 1.5, parameterized types can be assigned to a class during definition. The parameterized types will be substituted with the types specified at the class's instantiation. It is done by the compiler. It is similar to the C language macro '#define' statement, where a preprocessor evaluates the macros.
Code listing 4.1: Employee.java
public class Employee { // This defines the Employee class.
// The public modifier indicates that
// it can be accessed by any other class
private static int nextID; // Define a static field. Only one copy of this will exist,
// no matter how many Employees are created.
private int myID; // Define fields that will be stored
private String myName; // for each Employee. The private modifier indicates that
// only code inside the Employee class can access it.
public Employee(String name) { // This is a constructor. You can pass a name to the constructor
// and it will give you a newly created Employee object.
myName = name;
myID = nextID; // Automatically assign an ID to the object
nextID++; // Increment the ID counter
}
public String getName() { // This is a member method that returns the
// Employee object's name.
return myName; // Note how it can access the private field myName.
}
public int getID() { // This is another member method.
return myID;
}
public static int getNextID() { // This is a static method that returns the next ID
// that will be assigned if another Employee is created.
return nextID;
}
}
|
The following Java code would produce this output:
|
|
Constructors
editA constructor is called to initialize an object immediately after the object has been allocated:
Code listing 4.3: Cheese.java
public class Cheese {
// This is a constructor
public Cheese() {
System.out.println("Construct an instance");
}
}
|
Typically, a constructor is invoked using the new
keyword:
Code section 4.1: A constructor call.
Cheese cheese = new Cheese();
|
The constructor syntax is close to the method syntax. However, the constructor has the same name as the name of the class (with the same case) and the constructor has no return type. The second point is the most important difference as a method can also have the same name as the class, which is not recommended:
Code listing 4.4: Cheese.java
public class Cheese {
// This is a method with the same name as the class
public void Cheese() {
System.out.println("A method execution.");
}
}
|
The returned object is always a valid, meaningful object, as opposed to relying on a separate initialization method. A constructor cannot be abstract
, final
, native
, static
, strictfp
nor synchronized
. However, a constructor, like methods, can be overloaded and take parameters.
Code listing 4.5: Cheese.java
public class Cheese {
// This is a constructor
public Cheese() {
doStuff();
}
// This is another constructor
public Cheese(int weight) {
doStuff();
}
// This is yet another constructor
public Cheese(String type, int weight) {
doStuff();
}
}
|
By convention, a constructor that accepts an object of its own type as a parameter and copies the data members is called a copy constructor. One interesting feature of constructors is that if and only if you do not specify a constructor in your class, the compiler will create one for you. This default constructor, if written out would look like:
Code listing 4.6: Cheese.java
public class Cheese {
public Cheese() {
super();
}
}
|
The super()
command calls the constructor of the superclass. If there is no explicit call to super(...)
or this(...)
, then the default superclass constructor super();
is called before the body of the constructor is executed. That said, there are instances where you need to add in the call manually. For example, if you write even one constructor, no matter what parameters it takes, the compiler will not add a default constructor. The code listing 4.8 results in a runtime error:
Code listing 4.7: Cheese.java
public class Cheese {
public Cheese(int weight, String type) {
doStuff();
}
}
|
Code listing 4.8: Mouse.java
public class Mouse {
public void eatCheese() {
Cheese c = new Cheese(); // Oops, compile time error!
}
}
|
This is something to keep in mind when extending existing classes. Either make a default constructor, or make sure every class that inherits your class uses the correct constructor.
Initializers
editInitializers are blocks of code that are executed at the same time as initializers for fields.
Static initializers
editStatic initializers are blocks of code that are executed at the same time as initializers for static fields. Static field initializers and static initializers are executed in the order declared. The static initialization is executed after the class is loaded.
Code section 4.2: Static initializer.
static int count = 20;
static int[] squares;
static { // a static initializer
squares = new int[count];
for (int i = 0; i < count; i++)
squares[i] = i * i;
}
static int x = squares[5]; // x is assigned the value 25
|
Instance initializers
editInstance initializers are blocks of code that are executed at the same time as initializers for instance (non-static
) fields. Instance field initializers and instance initializers are executed in the order declared. Both instance initializers and instance field initializers are executed during the invocation of a constructor. The initializers are executed immediately after the superclass constructor and before the body of the constructor.