Date deadline
defines an object variable, deadline, that can refer to objects of type Date. It is important to realize that the variable deadline is not an object and, in fact, deos not even refer to an object yet
It is important to realize that an object variable doesn't actually contain an object. It only refers to an object
In Java, the value of any object variable is a reference to an object that is storedelsewhere. The return value of the new operator is also a reference
Date deadline = new Date();
The above sattement has two parts. The expression new Date() makes an object of type Date, and its value is a reference to that newly crated object. That reference is then stored in the deadline variable
You can explicitly set an object variable to null to indicate that it currentlyrefers to no object
Java object variables are similar to C++ references
All Java objects live on the heap. When an object contains another object variable, it contains just a pointer to yet another heap object
The LocalDate Class of the Java Library
The library designers decided to separate the concenrs of keeping time and attaching names to points in time. Therefore, the standard Java library contains two separte classes: the Date class, which represents a point in time, and the LocalDate class, which expresses days in the familiar calendar notation
You do not use a constructor to construct objects of the LocalDate class. Instead, use static factory methods that call constructors on your behalf
LocalDate.now()
LocalDate newYearsEve = LocalDate.of(1999, 12, 31);
int year = newYearsEve.getYear(); // 1999
int month = newYearsEve.getMonthValue(); // 12
int day = newYearsEve.getDayOfMonth(); // 31
LocalDate aThousandDaysLater = newYearsEve.plusDays(1000);
year = aThousandDaysLater.getYear(); // 2002
month = aThousandDaysLater.getMonthValue(); // 09
day = aThousandDaysLater.getDayOfMonth(); // 26
class ClassName {
field1
field2
...
constructor1
constructor2
...
method1
method2
...
}
Given that the example program consists of two classes: the Employee class and a class EmployeeTest with the public access specifier, the main method is contained in the EmployeeTest class, and the name of the source file is EmployeeTest.java because the name of the file must match the name of the public class
You can only have one public class in a source file, but you can have any number of nonpublic classes
Nextm when you compile this source code, the compiler creates two clas files in the directory: EmployeeTest.class and Employee.class
You then start the program by giving the bytecode interpreter the name of the class that contains the main method of your program
Use of Multiple Source Files
If you put different classes into different java files, you can invoke the Java compiler with a wildcard:
javac Employee*.java
//or
javac EmployeeTest.java
When the compiler sees the Employee class being used inside EmployeeTEst,java, it will look for a file named Emloyee.class. If it does not find that file, it automatically searches for Employee.java nd compiles it
Constructors
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
All Java objects are constructed on the head and that a constructor must be combined with new
Note that do not declare local variables inside a constructor, which is only accessible inside the constructor
Declaring Local Variables with var
As of Java 10, you can declare local variables with the var keyword instead of specifiying hteir type, provided their type can be inferred from the initial value
Working with null References
Permissive approach
turn a null argument into an appropriate non-null value
Tough approach
reject a null argument
Objects.requireNonNull(n, "the name cannot be null");
Implicit and Explicit Parameters
public void raiseSalary(double byPercent)
{
double raise = this.salary * byPercent / 100;
this.salary += raise;
}
// number007.raiseSalary(5);
The raiseSalary method has two parameters. The first parrameter, 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
In every method, the keyword this refers to the implicit parameter
Benefits of Encapsulation
If you want to get and set the value of an instance field, then you need to supply three items
A private data field
A public field accessor method; and
Be careful not to write accessor methods that returm references to mutatble objects, because this will lead to the break of encapsulation (the returned reference and the private field refer to the same mutable 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 stored in a new location
A public field mutator method
Benefits
You can change hte internal implementation without affecting any code other than the methods of the class
Mutator methods can perform error checking
Class-Based Acess Privileges
A method of an object class is permitted to acess the private fields of any object of the same type
class Employee
{
. . .
public boolean equals(Employee other)
{
return name.equals(other.name);
}
}
Private Methods
Sometimes, you may wish to break up the code for a computation into separate helper methods. Typically, htese helper methods should not be part of hte public interface - they may be too close to the current implementation or require a special protocol or calling order. Such methods are best implemented as private
As long as the method is private, the designers of the class can be assured that it is never used elsewhere, so they can simply drop it
Final Instances Fields
You can define an instance field as final. Such a field must be initialized when the object is contructed. Afterwards, the field may not be modified again
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)
The final keyword for a object reference merely means that the object reference stored in a variable will never again refer to a different object, but the object can be mutated
public class Math
{
. . .
public static final double PI = 3.14159265358979323846;
. . .
}
You can access this constant in your program as Math.PI. If the keyword static had been omitted, the nPI would have been an instance field of the Math class. Then you would need an object of this class to access Pi
Another static constant that you have used many times is System.out. It is declared in the System class as follows:
public class System
{
. . .
public static final PrintStream out = . . .;
. . .
}
Note that public constants are fine since they has been declared as final, you cannot reassign another print stream to it
If you look at the System class, you will notice a method setOut that sets System.out to a different stream. You may wonder how that method can cahnge the value of a final varaible. However, the setOut method is a native method, not implemented in the Java programming language. Native methods can bypass the access control mechanisms f the Java language
Static Methods
Static methods are methods that do not operate on objects
Math.pow(x, a)
The above expression computes the power of x to a. It does not use any Math object to carry out its task
You can think of static methods as methods that don't have a this parameter
A static method cannot acess instance fields because it does not operate on an object. However, a staic method can access a static field
It is legal to use an object to call a static method. However, it is recommended to use the class name instead of the object reference
The situations to use static methods
When a method doesn't need to access the object state because all needed parameters are supplied as explicit parameters
When a method only needs to access static fields of the class
The meaning of static in Java: to denote variables and functions that belong t oa class but not to any particular object of the class
Factory Methods
A static method that is used to generate instances of objects
NumberFormat 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%
Above is how hte NumberFormat class yields formatter objects for various styles
Reasons to use a factory method
You can't give names to constructors. The constructor name is always the smae 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 constructed object. But the factory methods actually return objects of the calss DecimalFormat, a subclass tha inherits from NumberFormat
The main Method
The main method is a static method
The main method does not operate on any objects. In fact, when a proram starts, there aren't any objects yet. The static main method executes, and constructs the objects that the proram needs
Every class can have a main class, which can be useful for unit testing of classes
class Employee
{
public Employee(String n, double s, int year, int month, int day)
{
name = n;
salary = s;
hireDay = LocalDate.of(year, month, day);
}
. . .
public static void main(String[] args) // unit test
{
var 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, execute
// java Employee
// If the Employee class is a part of a larger application, you start the application with
// java Application
// and the main method of the Employee class is never executed
public static void tripleSalary(Employee x) // works
{
x.raiseSalary(200);
}
// harry = new Employee(...);
// tripleSalary(harry);
1. x is initialized with a copy of the value of harry - an object reference 2. The reaiseSalary method is applied to that object reference. The Employee object to which both x and harry refer gets its salary raised by 200 percent. 3. The method ends, and the parameter variable x is no longer in use. The object variable harry continues to refer to the object whose salary was tripled
Summary
A method cannot modify a parameter of a primitive type
A method can change the state of an object paramete
A method cannot make an object parameter refer to a new object
public Employee()
{
name = "";
salary = 0;
hireDay = LocalDate.now();
}
If you write a class with no constructors whatsoever, then a no-argument constructor is provided for you. This constructor sets all the instance fields to their default values
If a class supplies at least one constructor but does not supply a no-argument constructor, it is illegal to construct objects without supplying arguments
Keep in mind that you get a free no-argument constructor only when your class has no other constructors
Explicit Field Initialization
It is always a good idea to make sure that, regardless of the constructor call, every instance field is set ot something meaningful
class Employee
{
private String name = "";
...
}
The assignment is carried out before the constructor executes
The initialization value doesn't have to be a constant value
class Employee
{
private static int nextId;
private int id = assignId();
. . .
private static int assignId()
{
int r = nextId;
nextId++;
return r;
}
. . .
}
Parameter Names
single-letter parameter names
a + parameter names
shadow instance fields with the same name
this.salary = salary
Calling Another Constructor
The keyworkd this refers to the implicit parameter of a method. However, this keyword has a second meaning
If the first statement of a constructor has the form this(...), then the constructor calls another constructor of the same class
public Employee(double s)
{
// calls Employee(String, double)
this("Employee #" + nextId, s);
nextId++;
}
Initialization Blocks
Currently, we have seen two ways to initalizae a data field
By setting a value in a constructor
By assigning a value in the delcaration
The third mechanism in Java is called an initialization block. Class declarations can contain arbitrary blocks of code. These blocks are executed whenever an object of that class is constructed
class Employee
{
private static int nextId;
private int id;
private String name;
private double salary;
// object initialization block
{
id = nextId;
nextId++;
}
public Employee(String n, double s)
{
name = n;
salary = s;
}
public Employee()
{
name = "";
salary = 0;
}
. . .
}
In this example, the id field is initialized in the object initialization block, no matter which constructor is used to construct an object. The initialization block runs first, and then the body of the constructor is executed
Note: it is legal to define a variable after initializing it in an object initialization block
Order of operations
If the first line of the constructor calls a second constructor, then the second constructor executes with the provided arguments
Otherwise,
All data fields are initialized to their default values (0, false, or null)
All field initializers and initialization blocks are executed in the order in which they occur in the class declaration
The body of the constructor is executed
Initalize a static field
To initialize a static field, either supply an initial value or use a static initialization block
static
{
var generator = new Random();
nextId = generator.nextInt(10000);
}
Static initialization occurs when the class is first loaded
Object Destruction and the finalize Method
If a resource needs to be closed as soon as you have finised using it, supply a close method that does the necessary cleanup. You can call the close method when you are done with the object
If you can wait until the virtual machine exits, add a "shutdown hook" with the method Runtime.addShutfownHook
Note: do not use the finilize method for cleanup. That method was intended to be called before the garbage collector sweeps away an object, and it is now deprecated
import java.time.*;
Note that the above importation has no negative effect on code size compared to the explicit importation. However, if you import classes explicitly, the reader of your code knows exactly which classes you use
Note that you can use hte * notation to import a single package. You cnnot use import java.* or import java.*.* to import all packages with the java prefix
Naming conflict
Suppose you import both java.util and java.sql packages and use a Date class, which is common in both packages
Case 1: If you now use the Date class, you get a compile-time error
import java.util.*;
import java.sql.*;
Date today; // ERROR--java.util.Date or java.sql.Date?
Case 2: If you want to use the Date in one of the package, add an additional import statement
import java.util.*;
import java.sql.*;
import java.util.Date;
Case 3: If you need both Date classes, then use hte full package name with every class name
var deadline = new java.util.Date();
var today = new java.sql.Date(...);
Locating classes in packages is an activity of hte compiler. The bytecodes in class files always use full package names to refer to other classes
Static Imports
A form of the import statement permits the importing of satic methods and fields, not just classes
import static java.lang.System.*;
import static java.lang.System.out; // import a specific method
out.println("Goodbye, World"); //i.e., System.out
Addition of a Class into a Package
To place classes inside a pakcage, put hte name of the package at the top of your source file, before hte code that defines the classes in the package
package com.horstmann.corejava;
public class Employee
{
...
}
If you don't put a package statement in the source file, the nthe classes in that source file belong to the unnamed package. The unnamed package has no package name
Place source files into a subdirectory that matches the full package name
All source files in the com.horstmann.corejava package should be in a subdirectory com/hosrtmann/corejava
Examples
The PackageTest class belongs to the unnamed package
We have classes distributed over several packages (com.horsstmann.corejava nd com.mycompany)
In this situation, you sitll must compile and run classes from the base directory - the directory containing the com directory
javac com/mycompany/PayrollApp.java
java com.mycompany.PayrollApp
Note again that the compiler operates on files (with file sperators and an extension .java), whereas the Java interpreter loads a class (with dot separators)
Q: What is the difference between a compiler and a Java interpreter?
Package Access
If you don't specify either public or private, the feature (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 having package access
The Class Path
Classes are stored in subdirectories of the file system. The path to the class must match the package name
Class files can also be sotred in a JAR (Java archive) file. A JAR file ocntains multiple class files and subdirectories in a compressed format, saving space and improving peformance
Q: What is the difference between a JAR file and a package?
Sharing classes among programs
Place yoru class files inside a directory (e.g., /home/user/classdir). Note that this directory is the vase directory for the package tree
Place any JAR files insidea directory - for example, /home/user/archives
Set the class path. The class path is the collection of all locations that can contain class files
In UNIX, the elements on the class path are separated by colons
/home/user/classdir:.:/home/user/archives/archive.jar
In the above class, this class path contians
The base directory /home/user/classdir or c:\classdir
The current directory (.); and
The JAR file /home/user/archives/archive.jar
Starting with Java 6, you can specify a wildcard for a JAR file directory
/home/user/classdir:.:/home/user/archives/'*'
In UNIX, the * must be escaped to prevent shell expansion
Note: the javac compiler always looks for files in the current directory, but the java virtual machine launcher only looks into the current directory if the "." directory is on the class path. If you have no class path set, it's not a problem -- the default class path consists of the "." directory. But if you have set the clas path and forgot to include the "." directory, your programs will compile without error, but they won't run
Q: What is the difference between javac compiler and the java virtual machine launcher?
The class path lists all directories and archive files that are starting points for locating classes
Suppose we have the sample class path
/home/user/classdir:.:/home/user/archives/archive.jar
Suppose the virtual machine searches for the class file of the com.horstmann.corejava.Employee class. It first looks in the Java API classes. It won't find the class file there, so it turns to the class path. It then looks for the following files
/home/user/classdir/com/horstmann/corejava/Employee
com/horstmann/corejava/Employee.class starting from the
current directory
com/horstmann/corejava/Employee.class inside
/home/user/archives/archive.jar
The compiler has a harder time locating files than does the virtual machine. If you refer to a class without specifying its package, the compiler first needs to find out hte package that contains the class. It consults all import directives as possible sources for the class
import java.util.*;
import com.horstmann.corejava.*;
If the source code refers to a class Employee. The compiler then tries to find java.lang.Employee (because java.lang package is always imported by default), java.util.Employee, com.horstmann.corejava.Employee, and Employee in the current package. It searches for each of these classes in all of the locations of the class path. It is a compile-time error if more than one class is found
The compiler further looks at the source file to see if the source is newer than the class file. If so, the source file is recompiled automatically
If you import public classes, the compiler can easily locate source files for public classes
If you import a nonpublic class, the compiler seraches all source files of the current package to see which one defines the class
Setting the Class Path
It is best to specify the class path with the option -classpath
java -classpath /home/user/classdir:.:/home/user/archives/archive.jar
MyProg
An alternate approach is the CLASSPATH environment variable
export CLASSPATH=/home/user/classdir:.:/home/user/archives/archive.jar
Note that the above line is a impermanent change
jar cvf jarFileNmae file1 file2 ...
// example
// jar cvf CalculatorClasses.jar *.class icon.gif
c - Create a new or empty archive and adds files to it; v - Generates verbose output; f - Specifies the JAR file name as the second command-line argument
The Manifest
In addition to class files, images, and other resources, each JAR file contains a manifest file that describes special features of the archive
The manifest file is called MANIFEST.MF and is located in a special META-INF sub-directory of the JAR file
The manifest entries are grouped into sections
The first section in the manifest is called the main section. It applies to the whole JAR file
Subsequent entries can sepcify properties of named entities such as individual files, packages, or URLs. Those entries must begin with a Name entry. Sections are separeted by blank lines
Manifest-Version: 1.0
lines describing this archive
Name: Woozle.class
lines describing this file
Name: com/mycompany/mypkg/
lines describing this package
To edit the manifest, place the lines that you want to add to the manifest into a text file. Then run
jar cfm jarFileName manifestFileName ...
// to make a new JAR file with a manifest
jar cfm MyArchive.jar manifest.mf com/mycompany/mypkg/*.class
// to update the manifest of an existing JAR file
jar ufm MyArchive.jar manifest-additions.mf
Executable JAR Files
You can use the e option of the jar command to specify the entry point of your program - the cladss that you would normally specify when invoking the java program lancher
jar cvfe MyProgram.jar com.mycompany.mypkg.MainAppClass files to add
Alternatively, you canspecify the main class of your program in the manifest, including a statement of the from
Main-Class: com.mycompany.mypkg.MainAppClass
Note: the last line in the manifest must end with a newline character
With either method, users can simply start the program as
java -jar MyProgram.jar
Depending on the opearting system configuration, users may even be abel toe launch the application by double-clicking the JAR file icon. On Mac OS X, the operating system recognizes the ".jar" file extension and executes the Java program when you double-click a JAR file
Multi-Release JAR Files
With the introduction of modules and strgon encapusulation of packages, some previouly accessible internal APIs are no longer available. For example, you need to distribute different applications for Java 8 and Java 9 Users. To solve problems such as this one, Java 9 introduces multi-release JARs that can contain class files for different Java releases
For backward compatibility, the additional class files are placed in the META-INF/versions directory:
Suppose the Application class makes use of the CssParser class. Then the legacy Application.class file can be compiled to use com.usn.javafx.css.CssParser, while the Java 9 version uses javafx.css.CssParser. Java 8 knows nothing about the META-INF/versions directory and will simply load the legacy classes. When the JAR file is read by Java 9, the new version is used instead
To add versioned class files, use the --release flag
jar uf MyProgram.jar --release 9 Application.class
To build a multi-release JAR file from scratch, use the -C option and switch to a different class file directory for each version
jar cf MyProgram.jar -C bin/8 . --release 9 -C bin/9 Application.class
When compiling for different releases, use the --release flag and the -d flag to specify the output directory:
javac -d bin/8 --release 8
Note: Multi-release JARs are not intended for different versions of a program or library. The public APi of all classes should be the same for both releaess. The sole purpose of multi-release JARs is to enable a particular version of your program or library to work with multiple JDK releases
A Note about Comman-Line Options
Starting with Java 9, the Java tools are moving towards a more common option format where multiletter option names are preceded by double dashes, with single-letter shortcuts for common options
ls --human-readable
ls -h //equivalent to the above
Arguments of options with -- and multiple letters are separated by whitespace or an = sign
javac --class-path /home/user/classdir ...
javac --class-path=/home/user/classdir ...
Single-letter options without arguments can be grouped together
jar -cvf MyProgram.jar -e mypackage.MyProgram */*.class
/**
Each comment is placed immediately above the feature it describes
*/
Each /** ... */ documentation comment contains free-form text followd by tags
Tag
Each /** ... */ documentation comment contains free-form text followed by tags. A tag starts with an @, such as @since or @param
Free-form text
The first sentence of the free-form text should be a summary satement
In the free-from text, you can use HTML modifiers such as ... for emphasis
Images
If your comments contain links to other files such as images, place those files into a subdirectory, named doc-files, of the directory containing the source file
The javadoc utility will copy the doc-files directories and their contents from the source directory to the documentation directory
Class Comments
The class comment must be placed after any import statements, directly before hte class definition
/**
* A {@code Card} object represents a playing card, such
* as "Queen of Hearts". A card has a suit (Diamond, Heart,
* Spade or Club) and a value (1 = Ace, 2 . . . 10, 11 = Jack,
* 12 = Queen, 13 = King)
*/
public class Card
{
. . .
}
Note in the comment above, there is no need to add an "*" in front of every line
Method Comments
Each method comment must immediately precede the method that it describes
Tags
@param variable description
This tag adds an entry to the "parameters" section of the current method
@return description
@throws class description
This tag adds a note that this method may throw an exception
/**
* Raises the salary of an employee.
* @param byPercent the percentage by which to raise the salary (e.g., 10 means
* @return the amount of the raise
*/
public double raiseSalary(double byPercent)
{
double raise = salary * byPercent / 100;
salary += raise;
return raise;
}
Field Comments
You only need to document public fields - generally that means static constants
General Comments
@since
The tag @since text makes a "since" entry. The text can be any description of the version that introduced this feature. For example, @since 1.7.1
@author
@version
This tag makes a "version" entry. The text can be any description of hte current version
@see & @link
You can use hyperlinks to other relrevant parts of the javadoc documentation, or to exernal documents
@see: The tag @see reference adds a hpyerlink in the "see also" section. It can be used with both classes and methods. The reference can be one of the following
package.class#feature label
@see com.horstmann.corejava.Employee#raiseSalary(double)
The above line makes a link to the raiseSalary(double) method in the com.horstmann.corejava.Employee class. Then, the feature will be located in the current package or class
Note that you must use a #, not a period, to separate the class from the method or variable name
"text"
@see "Core Java 2 volume 2"
If the @see tag is followed by a " character, then the text is displayed in the "see also" section
@link
If you like, you can place hyperlinks to other classes or methods anywhere in any of your documention comments. Insert a special tag of the form
{@link package.class#feature label}
Package Comments
To generate package comments, you need to add a separate file in each package directory. You have two choices:
Supply a Java file named package-info.java. The file must contain an initial Javadoc comment, delimited wih /** and */, followed by a package statement. It should contain no further code or comments
Supply an HTML file named package.html. All text between the tags
... is extractedComment Extraction
docDirectory: this is the name of the directory whree you want the HTML files to go
Procedures
Change to the directory that contains the source files you want to document. If you have nested packages to document, such as com.horstmann.corejava, you must be working in the direcotry htat contains the subdirectory com
Run the command
javadoc -d docDirectory nameOfPackage
for a single package. Or run
javadoc -d docDirectory nameOfPackage1 nameOfPackage2. . .
to document multiple packages
Additional options
https://docs.oracle.com/javase/9/javadoc/javadoc.html
private String street;
private String city;
private String state;
private int zip;
Suppose the above private fields are in a Customer class. We can place these fields into a new class called Address. This way you can easily cope with changes to addresses, such as the need to deal with internatinoal addresses
Not all fields need individual field accessors and mutators
Break up classes that have too many responsibilities
A bad design example
public class CardDeck // bad design
{
private int[] value;
private int[] suit;
public CardDeck() { . . . }
public void shuffle() { . . . }
public int getTopValue() { . . . }
public int getTopSuit() { . . . }
public void draw() { . . . }
}
This class really implements two separate concepts: a deck of cards, with its shuffle and draw methods, and a card, with the methods to inspect its value and suit. It makes sense to introduce a Card class that represents an individual card
A good design example
public class CardDeck
{
private Card[] cards;
public CardDeck() { . . . }
public void shuffle() { . . . }
public Card getTop() { . . . }
public void draw() { . . . }
}
public class Card
{
private int value;
private int suit;
public Card(int aValue, int aSuit) { . . . }
public int getValue() { . . . }
public int getSuit() { . . . }
}
Make the names of your classes and methods reflect their responsibilities
A good convention is that a class name should be a noun (Order), or a noun preceded by an adjective (RushOrder), or a gerund (an "-ing" word, as in BillingAddress). As for methods, follow the standard convention that accessor methods begin with a lowercase get(getSalary) and mutator methods use a lowercase set(setSalary)
Prefer immutable classes
The problem with mutation is that it can happen concurrently when multiple htreads try to update an object at the same time