Chapter 4 Objects and Classes
4.1 Introduction to OOP
OOP puts the data first, then looks at the algorithms to operate on data.
4.1.1 Classes
A class is a template or blueprint from which objects are made.
All code you write in Java is inside a class.
Encapsulation (Information Hiding) is simply combining data and behavior in one package and hiding implementation details from the users of classes.
Instance field—bits of data in an object.
Methods—the procedures operate on the data.
Inheritance—extending a class to obtain another class.
4.1.2 Objects
3 key characteristics of objects:
- The objects’ behavior: what you can do with this object, or what method you can apply to it?
- The object’s state: how do objects react when you invoke this method?
- The object’s identity: how is the object distinguished from the others that have the same behavior and state?
Each object stores the information what it currently looks like.
The individual objects that are instances of a class always differ in their identity and usually differ in their states.
4.1.3 Identifying Classes
Rule of thumb:
Look for nouns in the problem analysis. Methods are corresponding to the verbs.
4.1.4 Relationships between Classes
Most common relationships:
-
- Dependence (“uses-a”)—A class depends on another class if its methods use or manipulate objects of that class.
- Aggregation (“has-a”)—Containment means objects of class A contain objects of class B.
- Inheritance (“is-a”) —If class A extends class B, class A inherits methods from class B but has more capabilities.
UML Notation for Class Relationships:
4.2.1 Objects and Object Variables
A constructor is a special method whose purpose is to construct and initialize objects.
Constructors always have the same name as the class name.
To construct an object:
new Constructor();
Define an object variable:
DataType variableName;
You must first initialize the variable:
2 choices:
- Initialized a variable with a newly constructed object.
variableName = new DataType();
2. Set the variable to refer to an existing object.
variableName = existingObject;
Object variable only refers to an object, not contain an object.
You can explicitly set an object variable to null to indicate that it currently refers to no object.
Local variables are not automatically initialized to null. You must initialize them either by calling new or by setting them to null.
An instance of a class has a state, namely a particular point in time.
Good Idea:
Use separate classes to express different concepts.
Use static factory methods that contain constructors on your behalf.
4.2.2 Mutator and Accessor Methods
The method yields a new object, which is then assigned to a variable. The original object remains unchanged.
Mutator method: after invoking it, the state of the object has changed.
Accessor method: the method that only accesses objects without modifying them.
4.3 Defining Your Own Classes
To build a complete program, you combine several classes, one of which has a main method.
4.3.1 An Example Class
The simplest form of a class:
class ClassName { field1; field2; ... Constructor1; Constructor2; ... method1; method2; ... }
The name of the source file must match the name of the public class, and you can have any number of nonpublic classes.
4.3.2 Use of Multiple Source Files
Two choices of compiling the program:
- Invoke the java compiler with a wildcard, then all source files matching the wildcard will be compiled into class files.
- Simply type
javac EachFile.java;
The class being used in this file will look for a file named by that class.
4.3.3 Dissecting the Class
public means that any method in any class can call the method.
private means that the only methods that can access the instances are methods of the class itself. No outside methods can read or write to these fields.
Classes will often contain instance fields of the class type.
4.3.4 First Steps with Constructors
You cannot apply a constructor to an existing object to reset the instance fields.
A class has more than 1 constructors.
A constructor takes 0, 1 or more parameters.
A constructor has no return value.
CAUTION: Don’t use variable names that equal the names of instance fields.
4.3.5 Implicit and Explicit Parameters
implictParameter.methodName(p1, p2, p3, ..., pn); // pn (n = 1,2,...,n) is an explicit parameter.
The keyword this refers to the implicit parameter.
4.3.6 Benefits of Encapsulation
Accessor methods that simply return the value of instance fields are sometimes called field accessors.
Sometimes, if you want to get and set the value of an instance field, then you need to supply 3 items:
- A private instance field;
- A public field accessor method;
- A public mutator method.
Benefits:
- You can change the internal implementation without any code other than methods of the class.
- Mutator methods can perform error checking.
Caution: Be careful not to write accessor methods that return references to mutable objects. 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 stored in a new location.
4.3.7 Class-based Access Privileges
A method can access the private data of the object on which it is invoked and all objects of its classes.
4.3.8 Private Methods
When implementing a class, we made all data fields private.
Helper methods should not be part of the public interface.
The method may be well harder to implement or unnecessary if the data representation changes.
4.3.9 Final Instance Fields
Final instance field must be initialized when the object is constructed. The field value has been set after the end of every constructor.
The field may not be modified again.
The final modifier is useful for fields whose type is primitive or immutable class.
4.4 Static fields and Methods
4.4.1 Static Fields
If you define a field as static, then there is one such field per class. The static fields belong to the class, not to any individual objects.
4.4.2 Static Constants
Two examples of static constants, PI and System.out.
Every Math object would have its own copy of PI.
Since out has been declared as final, you cannot reassign another print stream to it.
4.4.3 Static Methods
Static methods do not operate on objects. (They have no implicit parameter.)
A static method can access a static field.
Use static methods in 2 situations:
- All needed parameters are supplied as explicit parameters. (e.g. Math.pow(x, y))
- When a method only needs to access static fields of the class.
4.4.4 Factory Method
https://en.wikipedia.org/wiki/Factory_method_pattern
Why not use a constructor instead?
- You cannot give names to constructors.
- When you use a constructor, you cannot vary the type of the constructed object
4.4.5 The Main Method
main method is a static method.
When a program start, the static main method executes and constructs the objects that the program needs.
4.5 Method Parameters
CS Terms:
- Call by value: the method just gets the value that the caller provides.
- Call by reference: the method gets the location of the variable that the caller provides.
The Java always uses “call by value”. That means that the method gets a copy of all parameters’ value, and the method cannot modify the contents of any parameter variables passed to it.
The method gets a copy of the object reference, and both the original and the copy refers to the same object.
Summary of method parameters in Java:
- A method cannot modify a parameter of the primitive type.
- A method can change the state of an object parameter through a copy of the object reference.
- A method cannot make an object parameter refer to a new object.
4.6 Object Construction
4.6.1 Overloading
Overloading occurs if several methods have the same name but different parameters.
Overloading resolution: the compiler picks the correct method by matching the parameter types in the headers of various methods with the types of value used in the specific method call.
Java allows you to override any method. Thus, to completely describe a method, you need to specify its name together with parameter types. This is called the signature of the method. (The return type is not part of the signature.)
4.6.2 Default Field Initialization
Default value:
Numbers: 0
Boolean Value: false
Object references: null
You must always explicitly initialize local variables in a method.
4.6.3 The Constructor with No Arguments
The no-argument constructor sets all the instance fields to their default values.
If a class supplies at least one constructor but not supply a no-argument constructor, it’s illegal to construct without supplying arguments.
CAUTION: Get a free no-argument constructor only when your class has no other constructors.
4.6.4 Explicit Field Initialization
Good Idea: Regardless of constructor call, everything is set to something meaningful.
The assignment is carried out before the constructor executes. This syntax is useful if all constructors of a class need to set a particular instance field to the same value.
A field can be initialized with a method call.
4.6.5 Parameter Name
Single-letter parameter name;
Prefix each parameter with an “a”;
this.paramName = paramName;
4.6.6 Calling Another Constructor
If the statement of a constructor has the form
this(…);
then the constructor calls another constructor of the same class.
Benefit: You only need to write common construction code once.
4.6.7 Initialization Blocks
Initialization block is never necessary and is not common. The initialization block runs first then the body of constructor executed.
We suggest that you always place initialization blocks after the field definitions.
What happens in detail when a constructor is called:
- If the first line of the constructor calls a second constructor, the object is constructed with the second constructor before continuing with the body of this constructor.
- All data fields are initialized to their default values.
- All field initializers and initialization blocks are executed, in the order they occur.
- The body of the constructor is executed.
4.6.8 Object Destruction and the finalize Method
Destruction: methods for any clean-up code that may be needed when an object is no longer used.
Java does automatic garbage collection, manual memory reclamation is not needed.
Since some objects utilize a resource other than memory (such as a file), it’s important to reclaim and recycle resource.
(DEPRECATED) You can add a finalize method to any class, and it will be called before the garbage collector sweeps away the object.
An alternative is to add shutdown hooks with the method Runtime.add.ShutdownHook .
If a resource needs to be closed as soon as you have finished using it, you have to manage it manually by calling close method when you are done with the object.
4.7 Package
Java allows you to group classes in a collection called package.
The standard Java packages are examples of hierarchical packages. All standard Java packages are inside the java and javax hierarchies.
The main reason for using packages—to guarantee the uniqueness of class names.
Use an Internet domain name written in reverse.
e.g. com.horsetman.corejava
4.7.1 Class Importation
A class can use all classes from its own package and all public classes from other packages.
2 ways to access the public classes in another package:
- Add the full package name in front of every class name
- Import specific classes or the whole package. Place import statements at the top of your source files but below any package statements.
Name conflict—both packages have the same-name classes.
Solutions:
- By adding specific import statements
- Need both classes? Use full package name with every class name.
Locating classes in packages is the activity of compiler. The bytecodes in class files always use full package names to refer to other classes.
4.7.2 Static imports
import statements permit the importing of static methods and fields.
4.7.3 Addition of a Class into a Package
Default package: the package has no package name.
Place source files into a subdirectory that fully matches the full package name. The compiler places the class files into the same directory.
The compiler operates on files with file separator and an extension “.java”.
The java interpreter loads a class with dot separators.
Caution:
1. The compiler does not check the directory structure when it compiles source files.
2. The virtual machine won’t find the classes if the packages don’t match the directory.
4.7.4 Package Access
If you don’t specify either public or private, the feature (that is, the class, method, or variable) can be accessed by all methods in the same package.
Variables must explicitly be marked private, or they will default to be package-visible.
If you seal a package, no further classes can be added to it. Package sealing can address the issue of promiscuous package access.
4.8 The Class Path
JAR—Java Archive File
The path to the class must match the package name.
A JAR file contains multiple class files and subdirectories in a compressed format, saving space and improving performance.
JDK supplies a number of JAR files, and one or more JAR files are usually included to use a third-party library.
3 ways to share classes among classes:
- Place your class files inside the base directory for the package tree.
- Place any JAR files into a directory.
- Set the class path. The class path is the collection of locations that contain class files.
In UNIX, the elements on the class path are separated by colons “:”.
In Windows, the elements on the class path are separated by semicolons “;”.
The class path (wildcard available) contains:
1. The base directory
2. The current directory (.)
3. The JAR file
In UNIX, the * must be escaped to prevent shell expansion.
All JAR files (but not class files) in the archive directory are included in this class path.
The runtime library files are always searched for classes. Don’t include them explicitly in the class path.