3.1. Class Definition Syntax
At its simplest level, a class definition consists of the keyword
class
followed by the
public class Integer extends Number implements Serializable, Comparable {
// class members go here
}
Generic class declarations include additional syntax that is covered in Chapter 4.
Class declarations may include zero or more of the following modifiers:
A public class is visible to classes defined outside of its package. See Section 3.6 later in this chapter.
An
abstract
class is one whose implementation is incomplete and cannot be
The final modifier specifies that the class may not be extended. Declaring a class final may enable the Java VM to optimize its methods.
If a class is declared strictfp , all its methods behave as if they were declared strictfp . This rarely used modifier is discussed in Section 2.6 in Chapter 2.
A class cannot be both abstract and final . By convention, if a class has more than one modifier, they appear in the order shown.
3.2. Fields and
A class can be
Class fields
Class methods
Instance fields
Instance methods
The simple class definition for the class Circle , shown in Example 3-1, contains all four types of members.
public class Circle {
// A class field
public static final double PI= 3.14159; // A useful constant
// A class method: just compute a value based on the arguments
public static double radiansToDegrees(double rads) {
return rads * 180 / PI;
}
// An instance field
public double r; // The radius of the circle
// Two instance methods: they operate on the instance fields of an object
public double area() { // Compute the area of the circle
return PI * r * r;
}
public double circumference() { // Compute the circumference of the circle
return 2 * PI * r;
}
}
The following sections explain all four kinds of members. First, however, we cover field declaration syntax. (Method declaration syntax is covered in Section 2.6 later in this chapter.)
Field declaration syntax is much like the syntax for declaring local
int x = 1; private String name; public static final DAYS_PER_WEEK = 7; String[] daynames = new String[DAYS_PER_WEEK]; private int a = 17, b = 37, c = 53;
Field modifiers are comprised of zero or more of the following keywords:
These access modifiers specify whether and where a field can be used outside of the class that defines it. These important modifiers are covered in Section 3.6 later in this chapter. No more than one of these access modifiers may appear in any field declaration.
If present, this modifier specifies that the field is associated with the defining class itself rather than with each instance of the class.
This modifier specifies that once the field has been
This modifier specifies that a field is not part of the persistent state of an object and that it need not be serialized along with the rest of the object. Serialization is covered in Chapter 5.
Roughly speaking, a volatile field is like a synchronized method: safe for concurrent use by two or more threads. More accurately, volatile says that the value of a field must always be read from and flushed to main memory, and that it may not be cached by a thread (in a register or CPU cache).
A class field is associated with the class in which it is defined rather than with an instance of the class. The following line declares a class field:
public static final double PI = 3.14159;
This line declares a field of type
double
named
PI
and
The
static
modifier says that the field is a class field. Class fields are sometimes called static fields because of this
static
modifier. The
final
modifier says that the value of the field does not change. Since the field
PI
represents a constant, we declare it
final
so that it cannot be changed. It is a convention in Java (and many other languages) that constants are named with capital
The key point to understand about a static field is that there is only a single copy of it. This field is associated with the class itself, not with instances of the class. If you look at the various methods of the Circle class, you'll see that they use this field. From inside the Circle class, the field can be referred to simply as PI . Outside the class, however, both class and field names are required to uniquely specify the field. Methods that are not part of Circle access this field as Circle.PI .
A
public
class field is
As with class fields, class methods are declared with the static modifier:
public static double radiansToDegrees(double rads) { return rads * 180 / PI; }
This line declares a class method named
radiansToDegrees()
. It has a single parameter of type
double
and returns a
double
value. The body of the method is quite short; it
Like class fields, class methods are associated with a class, rather than with an object. When invoking a class method from code that exists outside the class, you must specify both the name of the class and the method. For example:
// How many degrees is 2.0 radians? double d = Circle.radiansToDegrees(2.0);
If you want to invoke a class method from inside the class in which it is defined, you don't have to specify the class name. However, it is often good style to specify the class name anyway, to make it clear that a class method is being invoked.
Note that the body of our Circle.radiansToDegrees( ) method uses the class field PI . A class method can use any class fields and class methods of its own class (or of any other class). But it cannot use any instance fields or instance methods because class methods are not associated with an instance of the class. In other words, although the radiansToDegrees() method is defined in the Circle class, it does not use any Circle objects. The instance fields and instance methods of the class are associated with Circle objects, not with the class itself. Since a class method is not associated with an instance of its class, it cannot use any instance methods or fields.
As we discussed earlier, a class field is essentially a global variable. In a similar way, a class method is a global method, or global function. Although
radiansToDegrees()
does not operate on
Circle
objects, it is defined within the
Circle
class because it is a utility method that is sometimes useful when working with circles. In many nonobject-oriented programming languages, all methods, or functions, are global. You can write complex Java programs using only class methods. This is not object-oriented programming, however, and does not take advantage of the power of the Java language. To do true object-oriented programming, we need to add instance fields and instance methods to our
Any field declared without the static modifier is an instance field :
public double r; // The radius of the circle
Instance fields are associated with instances of the class, rather than with the class itself. Thus, every Circle object we create has its own copy of the double field r . In our example, r represents the radius of a circle. Thus, each Circle object can have a radius independent of all other Circle objects.
Inside a class definition, instance fields are referred to by name alone. You can see an example of this if you look at the method body of the circumference() instance method. In code outside the class, the name of an instance method must be prefixed with a reference to the object that contains it. For example, if the variable c holds a reference to a Circle object, we use the expression c.r to refer to the radius of that circle:
Circle c = new Circle(); // Create a Circle object; store a reference in c c.r = 2.0; // Assign a value to its instance field r Circle d = new Circle(); // Create a different Circle object d.r = c.r * 2; // Make this one twice as big
Instance fields are key to object-oriented programming. Instance fields hold the state of an object; the values of those fields make one object distinct from another.
Any method not declared with the static keyword is an instance method. An instance method operates on an instance of a class (an object) instead of operating on the class itself. It is with instance methods that object-oriented programming starts to get interesting. The Circle class defined in Example 3-1 contains two instance methods, area( ) and circumference() , that compute and return the area and circumference of the circle represented by a given Circle object.
To use an instance method from outside the class in which it is defined, we must prefix it with a reference to the instance that is to be operated on. For example:
Circle c = new Circle(); // Create a Circle object; store in variable c c.r = 2.0; // Set an instance field of the object double a = c.area(); // Invoke an instance method of the object
If you're new to object-oriented programming, that last line of code may look a little
a = area(c);
Instead, we write:
a = c.area();
This is why it is called object-oriented programming; the object is the focus here, not the function call. This small syntactic difference is perhaps the single most important feature of the object-oriented paradigm.
The point here is that we don't have to pass an argument to
c.area()
. The object we are operating on,
c
, is implicit in the syntax. Take a look at Example 3-1 again. You'll notice the same thing in the signature of the
area( )
method: it doesn't have a parameter. Now look at the body of the
area( )
method: it uses the instance field
r
. Because the
area()
method is part of the same class that defines this instance field, the method can use the unqualified name
r
. It is
Another important thing to notice about the bodies of the area( ) and circumference() methods is that they both use the class field PI . We saw earlier that class methods can use only class fields and class methods, not instance fields or methods. Instance methods are not restricted in this way: they can use any member of a class, whether it is declared static or not.
Consider this line of code again:
a = c.area();
What's going on here? How can a method that has no parameters know what data to operate on? In fact, the area( ) method does have a parameter. All instance methods are implemented with an implicit parameter not shown in the method signature. The implicit argument is named this ; it holds a reference to the object through which the method is invoked. In our example, that object is a Circle .
The implicit
this
parameter is not shown in method signatures because it is usually not needed; whenever a Java method
You can use the this keyword explicitly when you want to make it clear that a method is accessing its own fields and/or methods. For example, we can rewrite the area() method to use this explicitly to refer to instance fields:
public double area() { return Circle.PI * this.r * this.r; }
This code also uses the class name explicitly to refer to class field
PI
. In a method this simple, it is not necessary to be explicit. In more complicated cases, however, you may find that it
In some cases, the this keyword is required, however. For example, when a method parameter or local variable in a method has the same name as one of the fields of the class, you must use this to refer to the field since the field name used alone refers to the method parameter or local variable. For example, we can add the following method to the Circle class:
public void setRadius(double r) {
this.r = r; // Assign the argument (r) to the field (this.r)
// Note that we cannot just say r = r
}
Finally, note that while instance methods can use the this keyword, class methods cannot. This is because class methods are not associated with objects.
Instance methods are one of the key features of object-oriented programming. That doesn't mean, however, that you should shun class methods. In many cases, it is
public static double area(double r) { return PI * r * r; }
It is perfectly legal for a class to define more than one method with the same name, as long as the methods have different parameters. Since this version of the area() method is a class method, it does not have an implicit this parameter and must have a parameter that specifies the radius of the circle. This parameter keeps it distinct from the instance method of the same name.
As another example of the choice between instance methods and class methods, consider defining a method named
bigger( )
that examines two
Circle
objects and returns whichever has the larger radius. We can write
bigger( )
as an instance method as
// Compare the implicit "this" circle to the "that" circle passed
// explicitly as an argument and return the bigger one.
public Circle bigger(Circle that) {
if (this.r > that.r) return this;
else return that;
}
We can also implement bigger( ) as a class method as follows:
// Compare circle a to circle b and return the one with the larger radius
public static Circle bigger(Circle a, Circle b) {
if (a.r > b.r) return a;
else return b;
}
Given two
Circle
objects,
x
and
y
, we can use either the instance method or the class method to determine which is bigger. The invocation syntax
Circle biggest = x.bigger(y); // Instance method: also y.bigger(x) Circle biggest = Circle.bigger(x, y); // Static method
Both methods work well, and, from an object-oriented design standpoint,
Throughout this book, we've seen a method named
System.out.println()
used to display output to the terminal window or console. We've never explained why this method has such an long,