Static Fields and
|
|
|
In most object-oriented programming languages, static fields are called
class fields
. The
|
Let's implement a simple method:
public void setId()
{
id = nextId;
nextId++;
}
Suppose you set the employee identification number for
harry.setId();
Then the id field of harry is set, and the value of the static field nextId is incremented:
harry. id = . . .; Employee. nextId++;
Static
public class Math
{
. . .
public static final double PI = 3.14159265358979323846;
. . .
}
You can access this constant in your programs as Math.PI .
If the keyword static had been omitted, then PI would have been an instance field of the Math class. That is, you would need an object of the Math class to access PI , and every Math object would have its own copy of PI .
Another static constant that you have used many times is System.out . It is declared in the System class as:
public class System
{
. . .
public static final PrintStream out = . . .;
. . .
}
As we mentioned several times, it is never a good idea to have public fields, because everyone can modify them. However, public constants (that is,
final
fields) are ok. Because
out
has been declared as
final
, you cannot
System.out = new PrintStream(. . .); // ERROR--out is final
NOTE
|
|
If you look at the
System
class, you will notice a method
setOut
that lets you set
System.out
to a different stream. You may
|
Static methods are methods that do not
Math.pow(x, a)
computes the power x a . It does not use any Math object to carry out its task. In other words, it has no implicit parameter.
You can think of static methods as methods that don't have a this parameter. (In a non-static method, the this parameter refers to the implicit parameter of the method—see page 112.)
Because static methods don't operate on objects, you cannot access instance fields from a static method. But static methods can access the static fields in their class. Here is an example of such a static method:
public static int getNextId()
{
return nextId; // returns static field
}
To call this method, you supply the
int n = Employee.getNextId();
Could you have omitted the keyword static for this method? Yes, but then you would need to have an object reference of type Employee to invoke the method.
NOTE
|
|
It is legal to use an object to call a static method. For example, if
harry
is an
Employee
object, then you can call
harry.getNextId()
instead of
Employee.getnextId()
. However, we find that notation confusing. The
getNextId
method doesn't look at
harry
at all to compute the result. We recommend that you use class
|
You use static methods in two situations:
When a method doesn't need to access the object state because all needed parameters are supplied as explicit parameters (example: Math.pow )
When a method only needs to access static fields of the class (example: Employee.getNextId )
C++ NOTE
|
|
Static fields and methods have the same functionality in Java and C++. However, the syntax is slightly different. In C++, you use the :: operator to access a static field or method outside its scope, such as Math::PI .
The term "static" has a
|
Here is another common use for static methods. The NumberFormat class uses factory methods that yield formatter objects for various styles.
NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(); NumberFormat percentFormatter = NumberFormat.getPercentInstance(); double x = 0.1; System.out.println(currencyFormatter.format(x)); // printsNumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(); NumberFormat percentFormatter = NumberFormat.getPercentInstance(); double x = 0.1; System.out.println(currencyFormatter.format(x)); // prints $0.10 System.out.println(percentFormatter.format(x)); // prints 10%.10 System.out.println(percentFormatter.format(x)); // prints 10%
Why doesn't the NumberFormat class use a constructor instead? There are two reasons:
You can't give names to constructors. The constructor name is always the same as the class name. But we want two different names to get the currency instance and the percent instance.
When you use a constructor, you can't vary the type of the
Note that you can call static methods without having any objects. For example, you never construct any objects of the Math class to call Math.pow .
For the same reason, the main method is a static method.
public class Application
{
public static void main(String[] args)
{
// construct objects here
. . .
}
}
The main method does not operate on any objects. In fact, when a program starts, there aren't any objects yet. The static main method executes, and constructs the objects that the program needs.
TIP
|
|
Every class can have a main method. That is a handy trick for unit testing of classes. For example, you can add a main method to the Employee class:
class Employee
{
public Employee(String n, double s, int year, int month, int day)
{
name = n;
salary = s;
GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
hireDay = calendar.getTime();
}
. . .
public static void main(String[] args) // unit test
{
Employee e = new Employee("Romeo", 50000, 2003, 3, 31);
e.raiseSalary(10);
System.out.println(e.getName() + " " + e.getSalary());
}
. . .
}
If you want to test the Employee class in isolation, you simply execute java Employee If the employee class is a part of a larger application, then you start the application with java Application and the main method of the Employee class is never executed. |
The program in Example 4-3 contains a simple version of the
Employee
class with a static field
nextId
and a static method
getNextId
. We fill an array with three
Employee
objects and then print the employee information. Finally, we print the
Note that the Employee class also has a static main method for unit testing. Try running both
java Employee
and
java StaticTest
to execute both main methods.
1. public class StaticTest
2. {
3. public static void main(String[] args)
4. {
5. // fill the staff array with three Employee objects
6. Employee[] staff = new Employee[3];
7.
8. staff[0] = new Employee("Tom", 40000);
9. staff[1] = new Employee("Dick", 60000);
10. staff[2] = new Employee("Harry", 65000);
11.
12. // print out information about all Employee objects
13. for (Employee e : staff)
14. {
15. e.setId();
16. System.out.println("name=" + e.getName()
17. + ",id=" + e.getId()
18. + ",salary=" + e.getSalary());
19. }
20.
21. int n = Employee.getNextId(); // calls static method
22. System.out.println("Next available id=" + n);
23. }
24. }
25.
26. class Employee
27. {
28. public Employee(String n, double s)
29. {
30. name = n;
31. salary = s;
32. id = 0;
33. }
34.
35. public String getName()
36. {
37. return name;
38. }
39.
40. public double getSalary()
41. {
42. return salary;
43. }
44.
45. public int getId()
46. {
47. return id;
48. }
49.
50. public void setId()
51. {
52. id = nextId; // set id to next available id
53. nextId++;
54. }
55.
56. public static int getNextId()
57. {
58. return nextId; // returns static field
59. }
60.
61. public static void main(String[] args) // unit test
62. {
63. Employee e = new Employee("Harry", 50000);
64. System.out.println(e.getName() + " " + e.getSalary());
65. }
66.
67. private String name;
68. private double salary;
69. private int id;
70. private static int nextId = 1;
71. }
|
|