Defining Your Own Classes Core Java

However, all those classes had just asingle main method. Now the time has come to show you how to write the kind of “workhorseclasses” that are needed for more sophisticated applications. These classes typicallydo not have a main method. Instead, they have their own instance fields andmethods. To build a complete program, you combine several classes, one of which has amain method.

An Employee Class

The simplest form for a class definition in Java is

NOTE: We adopt the style that the methods for the class come first and the fields come at the end. Perhaps this, in a small way, encourages the notion of looking at the interface first and paying less attention to the implementation.

Consider the following, very simplified, version of an Employee class that might be usedby a business in writing a payroll system.

We break down the implementation of this class in some detail in the sections that follow. First, though, Listing below shows a program that shows the Employee class in action. In the program, we construct an Employee array and fill it with three employee objects:

Next, we use the raise Salary method of the Employee class to raise each employee’s salary by5%:

Finally, we print out information about each employee, by calling the get Name, get Salary,and get Hire Day methods:

Note that the example program consists of two classes: the Employee class and a classEmployeeTest with the public access specifier. The main method with the instructions that wejust described is contained in the EmployeeTest class.

The name of the source file is Employee Test. java because the name of the file must matchthe name of the public class. You can have only one public class in a source file, but youcan have any number of nonpublic classes.

Next, when you compile this source code, the compiler creates two class files in the directory:

You start the program by giving the byte code interpreter the name of the class that contains the main method of your program:

The bytecode interpreter starts running the code in the main method in the Employee Testclass. This code in turn constructs three new Employee objects and shows you their state.

EmployeeTest.java

Use of Multiple Source Files

The program in Listing has two classes in a single source file. Many programmersprefer to put each class into its own source file. For example, you can place the Employee class into a file Employee. java and the Employee Test class into EmployeeTest.java.

If you like this arrangement, then you have two choices for compiling the program. Youcan invoke the Java compiler with a wildcard:

Then, all source files matching the wildcard will be compiled into class files. Or, you can simply type

You may find it surprising that the second choice works even though the Employee. javafile is never explicitly compiled. However, when the Java compiler sees the Employee class being used inside Employee Test.java, it will look for a file named Employee.class. If itdoes not find that file, it automatically searches for Employee. java and then compiles it.Even more is true: if the time stamp of the version of Employee .java that it finds is newerthan that of the existing Employee.class file, the Java compiler will automatically recompile the file.

NOTE: If you are familiar with the “make” facility of UNIX (or one of its Windows cousins such as “nmake”), then you can think of the Java compiler as having the “make” functionality already built in.

Dissecting the Employee Class

In the sections that follow, we want to dissect the Employee class. Let’s start with the methodsin this class. As you can see by examining the source code, this class has one constructorand four methods:

All methods of this class are tagged as public. The keyword public means that any methodin any class can call the method.

Next, notice that three instance fields will hold the data we will manipulate inside an instance of the Employee class.

The private keyword makes sure that the only methods that can access these instance fieldsare the methods of the Employee class itself. No outside method can read or write to these fields.

NOTE: You could use the public keyword with your instance fields, but it would be a very bad idea. Having public data fields would allow any part of the program to read and modify the instance fields. That completely ruins encapsulation. Any method of any class can modify public fields—and, in our experience, some code usually will take advantage of that access privilege when you least expect it. We strongly recommend that you always make your instance fields private.

Finally, notice that two of the instance fields are them selves objects: the name and hireDay fields are references to String and Date objects. This is quite usual: classes will often containinstance fields of class type.

First Steps with Constructors

Let’s look at the constructor listed in our Employee class.

As you can see, the name of the constructor is the same as the name of the class. This constructor runs when you construct objects of the Employee class —giving the instance fields the initial state you want them to have.

For example, when you create an instance of the Employee class with code like this:

There is an important difference between constructors and other methods. A constructorcan only be called in conjunction with the new operator. You can’t apply a constructorto an existing object to reset the instance fields. For example,

We have more to say about constructors later. For now, keep the followingin mind:

  • A constructor has the same name as the class.
  • A class can have more than one constructor.
  • A constructor can take zero, one, or more parameters.
  • A constructor has no return value.
  • A constructor is always called with the new operator.

C++ NOTE: Constructors work the same way in Java as they do in C++. But keep in mind that all Java objects are constructed on the heap and that a constructor must be combined with new. It is a common C++ programmer error to forget the new operator:

That works in C++ but does not work in Java.

CAUTION: Be careful not to introduce local variables with the same names as the instance fields. For example, the following constructor will not set the salary:

The constructor declares local variables name and salary. These variables are only accessible inside the constructor. They shadow the instance fields with the same name. Some programmers—such as the authors of this book—write this kind of code when they type faster than they think, because their fingers are used to adding the data type. This is a nasty error that can be hard to track down. You just have to be careful in all of your methods that you don’t use variable names that equal the names of instance fields.

Implicit and Explicit Parameters

Methods operate on objects and access their instance fields. For example, the method

sets a new value for the salary instance field in the object on which this method is invoked. Consider the call

The effect is to increase the value of the number 007.salary field by 5%. More specifically, thecall executes the following instructions:

The raise Salary method has two parameters. The first parameter, called the implicit parameter,is the object of type Employee that appears before the method name. The second parameter,the number inside the parentheses after the method name, is an explicit parameter.

As you can see, the explicit parameters are explicitly listed in the method declaration, forexample, double byPercent. The implicit parameter does not appear in the method declaration.

In every method, the keyword this refers to the implicit parameter. If you like, you canwrite the raiseSalary method as follows:

Some programmers prefer that style because it clearly distinguishes between instancefields and local variables.

C++ NOTE: In C++, you generally define methods outside the class:

If you define a method inside a class, then it is automatically an inline method.

In the Java programming language, all methods are defined inside the class itself. This does not make them inline. Finding opportunities for inline replacement is the job of the Java virtual machine. The just-in-time compiler watches for calls to methods that are short, commonly called, and not overridden, and optimizes them away.

Benefits of Encapsulation

Finally, let’s look more closely at the rather simple get Name, get Salary, and ge tHire Day methods.

These are obvious examples of accessor methods. Because they simply return the valuesof instance fields, they are sometimes called field accessors.

Wouldn’t it be easier to simply make the name, salary, and hireDay fields public, instead ofhaving separate accessor methods?

The point is that the name field is a read -only field. Once you set it in the constructor,there is no method to change it. Thus, we have a guarantee that the name field willnever be corrupted.

The salary field is not read-only, but it can only be changed by the raiseSalary method.In particular, should the value ever be wrong, only that method needs to bedebugged. Had the salary field been public, the culprit for messing up the valuecould have been anywhere.
Sometimes, it happens that you want to get and set the value of an instance field. Thenyou need to supply three items:

  • A private data field;
  • A public field accessor method; and
  • A public field mutator method.

This is a lot more tedious than supplying a single public data field, but there are considerable benefits.

First, you can change the internal implementation without affecting any code other than the methods of the class.

For example, if the storage of the name is changed to

then the getName method can be changed to return

This change is completely invisible to the remainder of the program.

Of course, the accessor and mutator methods may need to do a lot of work and convertbetween the old and the new data representation. But that leads us to our second benefit:Mutator methods can perform error -checking, where as code that simply assigns to afield may not go to the trouble. For example, a setSalary method might check that the salaryis never less than 0.

CAUTION: Be careful not to write accessor methods that return references to mutable objects.

We violated that rule in our Employee class in which the getHireDay method returns an object of class Date:

This breaks the encapsulation! Consider the following rogue code:

The reason is subtle. Both d and harry.hireDay refer to the same object Applying mutator methods to d automatically changes the private state of the employee object!

If you need to return a reference to a mutable object, you should clone it first. A clone is an exact copy of an object that is stored in a new location. Here is the corrected code:

As a rule of thumb, always use clone whenever you need to return a copy of a mutable data field.

Returning a reference to a mutable data field

Returning a reference to a mutable data field

Class-Based Access Privileges

You know that a method can access the private data of the object on which it is invoked.What many people find surprising is that a method can access the private data of allobjects of its class. For example, consider a method equals that compares two employees.

This method accesses the private fields of harry, which is not surprising. It also accesses the private fields of boss. This is legal because boss is an object of type Employee, and a method ofthe Employee class is permitted to access the private fields of any object of type Employee.

C++ NOTE: C++ has the same rule. A method can access the private features of any object of its class, not just of the implicit parameter.

Private Methods

When implementing a class, we make all data fields private because public data are dangerous. But what about the methods? While most methods are public, private methods are used in certain circumstances. Sometimes, you may wish to break upthe code for a computation into separate helper methods. Typically, these helper methods should not become part of the public interface—they may be too close tothe current implementation or require a special protocol or calling order. Such methodsare best implemented as private.

To implement a private method in Java, simply change the public keyword to private.By making a method private, you are under no obligation to keep it available if you change to another implementation. The method may well be harder to implement orunnecessary if the data representation changes: this is irrelevant. The point is that as longas the method is private, the designers of the class can be assured that it is never usedoutside the other class operations and can simply drop it. If a method is public, you cannot simply drop it because other code might rely on it.

Final Instance Fields

You can define an instance field as final. Such a field must be initialized when the objectis constructed. That is, it must be guaranteed that the field value has been set after theend of every constructor. After wards, the field may not be modified again. For example,the name field of the Employee class may be declared as final because it never changes afterthe object is constructed —there is no set Name method.

The final modifier is particularly useful for fields whose type is primitive or an immutable class. (A class is immutable if none of its methods ever mutate its objects. For example,the String class is immutable.) For mutable classes, the final modifier is likely to confuse the reader. For example,

merely means that the object reference stored in the hiredate variable doesn’t get changed after the object is constructed. That does not mean that the hiredate object is constant.Any method is free to invoke the setTimemutator on the object to which hiredate refers.


All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

Core Java Topics