Notes for Core Java

programming_language


Author: Cay S. Horstmann
Volumn I - Fundamentals, Ninth Edition

before the notes:
From C++ to Java there are a lot of details that need to be paid attention to. And this book explains them quite clearly.

Chapter Three: Fundamental programming structures in Java

Data type

Variables

Variable names are case-sensitive.
The length of variable names are unlimited.
In Java, no declaration is seperated from definition.
e.g. such things like extern int i will not happen in Java.

Constants

use the key word final to denote a constant.
use static final inside a class to denote a class constant.

Operators

+, -, *, /, +=
++, --
==, !=
&&, ||
? :
bitwise operators: & | ^ ~
math functions and constants:
Math.sqrt(x)
Math.PI

Conversions between numeric types

Casts

the same as C++
int x = (int)9.9;
Boolean type can not be cast into any numeric type.
an alternative to conversion: b ? 1 : 0

String

  1. StringBuilder builder = new StringBuilder();
  2. builder.append("abc");
  3. String str = builder.toString();

Input & Output

To read a password, there is a little different.

  1. Console cons = System.console(); // a console object for interaction
  2. String name = cons.readline("User name: ");
  3. char[] password = cons.readPassword("Password: ");
  4. // for security reason, returns an array rather than a string.

Control Flow

Mostly they are identical to C++ or C, but there are slight differences.
The same things: if, while, for, switch

  1. Java has no goto, but a labeled break.
    Put the label with a colon before the loop. After the break, the control flow will jump across the whole loop.
  2. Redefining a variable inside a nested block is not allowed. In C++, the inner one shadows the outer one.

Big Numbers

in java.math package, use BigInteger and BigDecimal(floating-point).

Attention: Java does not allow programmable operator overloading. So you cannot use + or - to big numbers.

Arrays

An array is a date structure that stores a collection of values of the same type. You can access through index like a[1].

  1. for(double[] row: a){
  2. for(double value: row)
  3. ...
  4. }

Chapter Four: Objects and Classes

OOP

Niklaus Wirth, the designer of Pascal language said,

Algorithm + Data structure = Programs

This is the traditional understanding of programming, algorithm first and then data structure. But in object-oriented programming, data comes first, and then look at the algorithms.

Classes

Concepts:

Objects

Three things about an object:

indentify classes

Nouns are class. Verbs are methods.
More commonly, experience-based.

relationship between classes

UML notation

Object Variable

An object variable does not contain an object. It only refers to an object.

Java object variables are analogous to C++ object pointers.
Date birthday; // Java
is the same as
Date* birthday; // C++

accessor: get methods
mutator: set methods

Customer-defined Classes

One source file has only one public class and any number of nonpublic class. The name of the source file must match that of the public class.
The compiler will create .class file for each class.

Recommendation: make all instance field private, except for public final fields.

Constructors

A constructor

One of the common error for C++ programmer to code in Java is forgetting the new when creating an object.

Be careful not to introduce local variables inside constructors with the same name as instance fields.

Implicit and explicit parameters

Explicit parameters are explicitly listed in the declearation of the method, while the implicit one is the object of type that appears before the method name.
The key word thiscan be used to refer to the implicit parameter.

Unlike C++, all methods of Java classes are defined inside the class. JVM decides which method is inline.

Encapulation

To get and set the value of an instance field, we need

If an accessor wants to return references to mutable objects, it should be cloned first by .clone() method. Otherwise encapsulation will be breaken.

Access privileges are class-based, not instance-based.
Therefore, a method can access the private data of all objects of this class.

Final

Final instance fields must be initialized when the object is constructed. Having set the final field value must be guaranteed after the end of every constructor.

If an object variable is declared as final, it does not mean that the object itself is constant but the object reference that stored in the variable does not change after construction.

Static

If a field is defined static, then there is only one such field per class.
Static variables are rare. Static constants are more common.
And public constants are OK because no one can modify.
public static final

Static methods are used in two situations:

main

The main method does not operate on any object. Every class can have a main method. It is a handy trick for unit testing.

Method parameters

Java always uses call by value.
Methods get a copy of all parameter values passed to it and cannot modify the contents of any parameter variables.

A method

Object Construction

Constructors can be overloaded.
Default field initialization.
There is a free no-argument constructor only when my class has no other constructors.

Destruction

Java does automatic garbage collection.
A finalize method will be called before it. But do not rely on it for resource recycling.
Instead, supply a close method that does the cleanup.

Package

A package is a collection of classes.
The standard Java package is inside the java and javax package hierachies.
The main reason for using package is to guarantee the uniqueness of class names. Classes in different packages can have the same name.
To guarantee the uniqueness of package name, use your domain name in reverse.
There is no relationship between nested packages.

Importation

A class can use all classes from its own package and all public classes from other package.
To access classes from other packages, use its full name or use import for short.

The package and import in Java is analogous to the namespace and using in C++, rather than #include.

Static import

import static + package_name
To use the static methods andd fields of the class without prefix

Addition of a class into a package

put the package statement at the top of the source file
package com.mycompany.corejave;
Otherwise, it will be in the default package.

To complile in the command line:
javac com/mycompany/corejave/wedget.java
java com.mycompany.corejave.wedget
The compiler looks for files, while the interpreter looks for classes, which accounts for the differ of their paths.

If the feature(class, method, variable) does not have public or private modifier, it is package-visible. Classes from the same package can access it. This will break encapsulation.

package sealing: no further classes can be added. (Chapter 10)

class path

Class files can be stored in a JAR(Java Archive) file which contains multiple class files adn subdirectories in a compressed ZIP format.

To share classes among programmers,
1. Place class files inside a directory.
2. Place any JAR files inside another directory.
3. Set the class path - The base directory, the JAR file and the current directory (.)

The compiler always looks for files in the current directory. But JVM only looks into the current directory if the "." is on the class path.

ways for setting the class path:
1. using command java -classpath + the three paths
2. set CLASSPATH environment variable in different shells
Do not set CLASSPATH permanently!

Documentation Comments

javadoc is a tool in JDK that generates HTML documentation from source files.

Insertion

javadoc looks for

The comment is placed above the feature it described.
Start with /**, end with */
Tags start with @
You can use HTML modifiers.

  1. Class Comments
    must be placed after any import statements, before the class definition.

  2. Method Comments

    • @param variable_name discription
    • @return description
    • @throws class description
  3. Field Comments
    Only need to document public field - static constants.

  4. General Comments

    • @author name
    • @version text
    • @see reference
  5. Package Comments
    supply an HTML file named package.html and all text in its body will be extracted.

To generate documentation, run
javadoc -d docDirectory nameOfPackage1 nameOfPackage2 ...

Class Design Hints

Chapter 5: Inheritance

Superclasses and subclasses

In C++, we use class derived: public base{ ... } to inheritate, base::method() to call base methods, Derived(init_list): Base(init_list){ ... } to construct the part of the superclass.

Polymorphism: An object variable can refer to multiple actual types.
Dynamic binding: Automatically select the appropriate method at runtime.

Dynamic binding is default in Java. You don't have to declare virtual as C++.

Java does not support multiple inheritance. Use interface instead.

Overriding can change the return type of a method to a subtype of the orinal one.

The subclass method that overrides that of the superclass must be declared as public as well.

Casting

  1. if(x instance of SubClass){ // false if x is null
  2. SubClass sub = (SubClass)x;
  3. }
  4. // in c++
  5. SubClass* sub = dynamic_cast<SubClass*>(x);
  6. if(sub != NULL){

Abstract Classes

When a abstract class is extended, there are two choices:

In C++, a class is abstract if it has at least one pure virtual function such as virtual void f() = 0;

Protected Access

use with caution in fields
make more sense to methods

protected in Java is less safe than in C++, because
other classes in the same package can access it.

Summary of accessibility

  1. private visible to the class only
  2. public visible to the world
  3. protected visible to the package and all subclasses
  4. (default) visible to the package

The Cosmic Superclass: Object

Every class in Java extends Object.
In Java, only premitive types (numbers, characters and boolean) are not objects.

Equality Testing

testing equality between a subclass and a superclass
two senarios:

The recipe for equals method:

  1. the explicit parameter for the method is Object otherObject.
    And this will override the one of the Object class.
  2. Test whether this happens to be identical to otherObject.
  3. Test whether otherObject is null.
  4. Compare the class of this and otherObject.
    If the sematics of equals can change in subclasses, use the getClass test.
    If the same sematics holds for all subclasses, use the instanceof test.
  5. Cast otherObject to a variable of your class type.
  6. Compare the fields. Use == for primitive types and Object.equals for objects.
  7. If you redefine equals in a subclass, include a call to super.equals
  1. public boolean equals(Object otherObject){
  2. // 2.
  3. if(this == otherObject) return true;
  4. // 3.
  5. if(otherObject == null) return false;
  6. // 4.
  7. if(getClass() != otherObject.getClass()) return false;
  8. // or
  9. if(!(otherObject instanceof ClassName)) return false;
  10. // 5.
  11. ClassName other = (ClassName)otherObject;
  12. // 6.
  13. return field1 == other.field1
  14. && Object.equals(field2, other.field2)
  15. && ...;
  16. }

The hashcode method

The hashcode method is defined in the Object class.

If equals method is redefined, hashcode method needs to be redefined as well. And they must be compatible.
If two variables are equals under the equals method, they must have the same value of hash code.

Some relative methods:
int Object.hashcode() returns the hash code for this object (returns 0 for null).
int Object.hash(Object...Object) returns a combined hash code.
itn Array.hashcode(type[] a) computes the hash code of array a with different components.

The toString method

A common format for toString method:
getClass().getName() followed by field values in square brackets. For derived classes, add square brackets after.

The toString method is invoked automatically when contatenating a string with an object by "+" operator ,or printing an object by System.out.println().

Specifically, to print an array, use Array.toString(a) instead.
For a multimensional array, use Array.deepToString(a)

Adding a toString to a user-defined class is strongly recommended.

Generic Array List

ArrayList is a generic class with a type parameter in angle brackets.
ArrayList is similar to the C++ vector template.

Object Wrappers and Autoboxing

All primitive types have class counterparts.
They are called wrappers
Integer, Long, Float, Double, Short, Byte, Character, Void, Boolean
Wrapper classes are immutable and final.
A typical usage is to construct an ArrayList of integer.
Angle brackets do not recieve primitive types.
use ArrayList<Interger> list = new ArrayList<>() instead.

Autoboxing
list.add(3) does autoboxing to be list.add(Integer.valueOf(3))
In most cases, the primitive types and their wrappers are likely to be the same except for their identity.
Wrappers are a convenient place to put some basic methods.
The word "boxing" is taken from C#.

int Integer.intValue() return as an int
static String Integer.toString()
static int Integer.parseInt(String s, int radix) returns the integer contained in a string. The integer should be in the given base or default 10 base.
static Integer Integer.valueOf(String s, int radix) similar

Varargs Methods: methods with a variable number of parameters

public void f(int... list){ }
The ellipsis "..." is part of the code, which denotes the method receives an arbitary number of objects, and is exactly the same as Object[]. So for(int x: list) can be used for iteration.

To call the method, use f(1,2,3);.

Enumeration classes

Enumeration is actually a class with a fixed number of instances.
public enum MyEnum{SMALL, MEDIAN, LARGE };

Reflection

The Reflection Library provides tools for manipulating Java codes dynamically. A program that can analyze the capabilities of classes is called reflective.
It is a powerful and complex mechanism.
However, it is useful in system programming or toolkit design, not in applications.

The class class

The Java runtime system maintains runtime type identification on all objects, which keeps track on the class which each object belongs to.

A primer on Catching Exceptions

Using "try-catch" statement to catch exceptions.
The compiler will tell you which method need to supply a handler.

Using refection

The three classes Field, Method, Constructor in Java.lang.reflect package describe three aspects of the class respectively.
getName returns a name
getModifier returns an integer
Modifier.isPublic/isPrivate/... analyze the integer, return boolean
Field.getType
getFields, getMethods, getConstructors return arrays of the public fields, methods and constructors.
getDeclaredFields, getDeclaredMethods, getDeclaredConstructors return all, not just public ones.

Using Reflecton for analyzing objects at runtime

access field information by the get method of the Field class

  1. MyClass mc = new MyClass();
  2. Class cl = new mc.getClass();
  3. Field f = cl.getDeclaredField("field_name");
  4. Object obj = f.get(mc);
  5. // returns an object whose value is the current value of the field of mc

This method can only be used to access accessible fields. If the field is private, you can change its accessibility by setAccessible method on a Field, Method, Constructor object.
f.setAccessible(true);

As for number objects, get() does autoboxing.

Also, we can set value by set method
void Field.set(Object obj, Object newValue);

customize your own generic toString method used for all objects

Using reflectio to write Generic Array Code

Consider we are coding the implementation of the copyOf method of a geneic array that holds elements of any type.
Any object can be converted into Object class, but it would not help because an array of elements of Object class would not be cast back into the same type of array after the memory reallocation.
Therefore we would not cast an instance of MyClass[] into Object[] class. Rather, we treat the instance of MyClass[] as an Object and create a new array using reflect.Array.newInstance() based on this Object.

  1. public static Object copyOf(Object obj, int newLength){
  2. Class cl = obj.getClass();
  3. if(!cl.isArray()) return null;
  4. Class componentType = cl.getComponentType();
  5. int length = Array.getLength(cl);
  6. Object newArray = Array.newInstance(componentType, newLength);
  7. System.arraycopy(obj, 0, newArray, 0, Math.min(length, newLength));
  8. return newArray;
  9. }
  10. int[] a = {1,2,3,4};
  11. a = (int[])copyOf(a, 10);

Invoking arbitrary methods

Java has no method pointer because the designer thought it is dangerous and Java interface is an alternative.
Howeverm the reflection mechanism allows you to call arbitrary methods. Yet In a mush slower way.

Suggestion: use method class only when absolutely necessary.

Design Hints for Inheritance

  1. place common operations and fields in the superclass.
  2. Do not use protected fields.
  3. Use inheritance to model the "is-a" relationship.
  4. Do not use inheritance unless all inherited methods make sense.
  5. Do not change the expected behavior when overriding a method.
  6. Use polymorphism, not type information.
  7. Do not overuse reflection.

Chapter Six: Interfacces and Inner Classes

Two advanced techniques:

Interfaces

A interface is a set of requirements for the classes that want to conform to the interface.
For instance, if the sort method of Array class needs to be used to sort an array of objects, these objects must belong to classes that implement the Comparable interface which has a method called compareTo.

  1. public interface MyInterface{
  2. void f(); # not necessarily public
  3. double pi = 3.14; # auto public static final
  4. }

in Java SE 5.0, an interface can be generic.
public interface MyInterface<T>
class MyClass implements MyInterface<MyType>

Properties of Interfaces

The introduction of interfaces in Java aims to replace multiple inheritance.

Object Cloning

The clone method is declared protected in the Object class so you cannot simply call obj.clone().

When you decide to clone an object, decide:
1. The default clone method is good enough.
2. The default clone method can be patched up by calling clone on the mutable subobjects to avoid shallow copy.
3. cancel the cloning.

To choose either the first or the second choice, a class must:
1. implement the Cloneable interface.
2. redefine the clone method with publc modifier.
The Cloneable interface has nothing to do with the clone method which is inherited from Object class. It just serves as a tag to inform programmers. ("marker interface") But this is acutally a bad use.

  1. class MyClass implements Cloneable{
  2. public MyClass clone() throws CloneNotSupportedException
  3. {
  4. MyClass myClone = (MyClass)super.clone();
  5. // deep copy if necessary
  6. myClone.fields = (Type)fiels.clone();
  7. return myClone;
  8. }
  9. }

Specially, all array types have a public clone method instead of protected.

Cloning is less common than you think.
"Object serialization" is an alternative for cloning objects.

Callbacks

The callback pattern specifies the actions that should occur whenever a particular event happens.

For example, a timer wants to invoke an event after a ccertain time interval. The event is a class. The invoker is an interface with a method that takes the event as a parameter. And the listener implements this interface and supply the detail to invoke the event. Finally, the listener is passed to the timer as a parameter.
Whenever you would use a function pointer in C++, you should use an interface in Java.

Inner Class

An inner class is a class that is defined inside another class.

In C++, nested classes provide two benefits: name control (call the inner class with the name of outer class) & access control (classes in the private part are hidden from outside).

Access Object State

Special syntax rules

usefulness, necessity and security

The inner class is a phenomenon of the compiler.
The compiler translates the inner classes into nomal classes by concatenating the name of the outer class before them.
JVM knows nothing about inner classes.

Local Inner Classes

An inner class inside a method is called a local inner class.
Local classes are never declared with an access modifier.
Their scope is restricted to the block in which they are declared.
One great advantage: it is totally hidden from the outside. No one except the method has any idea of the inner class.

Accessing final variables

Local inner classes can access local final variables.
The inner class stores a copy of the local final varibles of the outer class when being constructed. So it is possible that the local final variable will be called by an object of the inner class even after the method ends.

Anonymous Inner Classses

Without names.

  1. new SuperType(construction parameters){
  2. //inner class methods and data
  3. }

Noted that SuperType can be an interface or a super class.

Static Inner Class

A inner class that is static does not have a reference to the outer class.
Only inner classes can be declared static.
Use a static inner class whenever the inner class does not need to access an outer class object.
Inner classes that are declared inside an interface are automatically static and public.

Proxies

use proxy when creating new classes that implements a set of interfaces that I do not know which to choose at compile time

A invocation handler is an object of any class that implements the InvocationHandler interface which has a single method invoke.

To create a proxy object, use the newProxyInstance method of the Proxy class.
We define different handlers for proxies with different purposes.

Proxy is an advanced technique for tool builders, not for application programmers.