General Notes:
- "Generic programming" is enabled by four object-oriented facilities:
- inheritance
- polymorphism
- generic binding
- interfaces
- A Cylinder class might inherit public methods from a
Circle class and extend the Circle class with its own data
fields and methods.
- Wrapper classes enable primitive data types to be treated
as objects.
- While a string is an object, a string buffer is an array of characters
- The StringTokenizer class is used to break a string into pieces so that
information contained in it can be retrieved and processes. We do this by
specifying a set of characters as delimiters when constructing a StringTokenizer
object... The delimiter breaks a string in tokens.
- The this keyword can be thought of as a surrogate for referring
to the calling object. The keyword super refers to the superclass
of the class in which it appears. The only way to refer to a superclass
from a subclass is by the super keyword.
- The keyword static preceding a data field or method identifies
them as class fields and methods. I.e. each object instantiated from the
class shares the same static field or method
- What is the difference between an interface and an abstract class
7 Strings
- In Java a string is an object (as opposed to an array of characters, as
in other languages)
- Java provides the String class, the
StringBuffer class, and the StringTokenizer
class for storing and processing strings
- The String class is immutable (java.lang.String)
- The StringBuffer class enables us
to create flexible strings that can be modified
- StringTokenizer is a utility class
that can be used to extract tokens for a string
Constructing a String
String newString = new String(stringLiteral);
or, in shorthand notation:
String newString = stringLiteral;
8 Inheritance and Polymorphism
- The statement super() or super(arguments)
must appear in the first line of the subclass constructor and is
the only way to invoke a superclass constructor.
- Constructor chaining: contructing an instance of a class
invokes the constructors of all the superclasses along the inheritance chain.
- CAUTION: If a class is designed to be extended, it is better to provide
a no-arg constructor to avoid errors. [291]
- Method overiding: when a subclass modifies the implementation
of a method defined in (and inherited from) its superclass.
- NOTE: To overide a method, the method must be defined in the subclass
using the same signature and return type as in its superclass. (This is
to be differentiated from method overloading, in which methods
within a class share the same name, but different signatures: i.e. type,
number and order of arguments.)
- NOTE: An instance method can be overriden only if it is accessible. If
a method defined in a subclass is private in its superclass, the two methods
are completely unrelated.
- NOTE: Like an instance method, a static method can be inherited. However,
static methods cannot be overriden. If a static method defined in the superclass
is redefined in the subclass, the method defined in the superclass is hidden.
- Every class in Java is descended from the java.lang.Object
class. If no inheritance is specified (using the keyword extends) when a
class is defined, the superclass of the class is Object.
We can however override the default implementation of methods in the Object
class. We look at three methods: equals(),
hashCode(), and toString()
below.
- The equals method tests whether two
objects are equal.
- NOTE: The == comparison operator is
used for comparing two primitive data type values or for determining whether
two objects have the same references. The equals
method is intended to test whether two objects have the same content, provided
that the method is modified in the defining class of the objects.
- CAUTION: In overriding the equals
method of the Object class, be sure
to use equals(Object obj) as the signature,
rather than the erroneous equals(SomeClassName
obj).
- Invoking hashCode() on an object returns
the object's hashcode. Hash code is an integer that can be used
to store the object in a hash set so that it can be located quickly (Hash
sets: Ch 18).
- Invoking the toString() method on
an object returns a string that represents the object. By default, it returns
a string consisting of a class name of which the object is an instance,
an at sign (@), and the object's hash code in hexadecimal. (Usually, we
would like to override the toString
method so that it returns an intelligible representation of an object.)
8.6 Polymorphism, Dynamic Binding, and Generic Programming
- Polymorphism: a feature that allows for an object of
a subclass to be used by any code designed to work with an object of its
superclass.
- Dynamic binding: a facility by which, upon the invocation
of a method by an object, the JVM searches the implementation for the method
is progressively higher classes in the hierarchical inheritance order until
it is found.. That is, given a hierarchical set of super- and subclasses
with various implementations of a method, and the invocation of that method
in an arbitrary object of one of the classes in the hierarchy, the JVM dynamically
determines the impletation to use at runtime by, again, searching in progressively
higher classes until it is found.
- NOTE: Matching a method signature and binding a method implementation
are two separate issues. The compiler finds a matching method according
to the type, number, and order of parameters at compilation time. A method
may be implemented in several subclasses. The JVM dynamically binds the
implementation of the method at runtime.
- Generic programming: a feature of polymorphism that allows
methods of be used generically for a wide range of object arguments. If
a method's parameter type is a superclass, we may pass an object to this
method of any of the the parameter's subclasses. When an object is used
in the method, the particular implementation of the method of the object
that is invoked is determined dynamically.
8.7 Casting objects and the instanceof
Operator
- We can use casting to convert an object of one class type to another within
an inheritance hierarchy.
- Implicit casting:
- Explicit casting:
- Upcasting: casting an instance of a subclass to a variable of a superclass
- Downcasting: casting an instance of a superclass to a variable of its
subclass; requires explicit casting
- instanceof keyword:
8.9 The protected Data and Methods
- A protected datum or a protected method in public class can be assessed
by any class in the same package or its subclasses, even if the
subclasses are in different packages.
- The visibility or accessibility of the modifiers in increasing order of
visibility: private, none (that is,
no modifier specified), protected, public.
- Use:
- the private modifier to hide the
members of the class completely so that they cannot be assessed directly
from outside the class;
- no modifier to allow members of the class to be assessed directly
from any class within the same package but not from other packages;
- the protected modifier to enable
members of the class to be accesses by the subclasses in any package
or classes in the same package;
- the public modifier to enable
the members of the class to be accessed by any class.
- Our class can be used in two ways:
- for creating instances of the class, and
- for creating subclasses by extending the class. Accordingly,
- Make the members private if they are not intended for use from
outside the class
- Make the members public if they are intended for users of the
class
- Make the members protected if they are intended for the extenders
of the class but not the users of the class
- The private and protected
modifiers can only be used for members of the class. The public
modifier and the default modifier (i.e. no modifier) can be used on members
of the class as well as on the class. A class with no modifier is not accessible
by classes from other packages.
- NOTE: A subclass may override a protected
method in its superclass and change its visibility to public.
However, a subclass cannot weaken the accessibility of a method defined
in the superclass. A method that is defined as public
in the superclass must remain defined as public
in the subclass.
8.10 The final Classes, Methods, and
Variables
- If we want to prevent a class from being extended, we use the final
modifier to indicate that the class is final and cannot be a parent class.
- We can also define a method to be final. A final method cannot be overridden
by the subclasses of the class in which the method is contained.
- (The final modifier can be used on
classes, class members (data and methods), and local variables in a method.
A final local variable is a constant.
8.11 The finalize, clone,
and getClass Methods
- The finalize, clone,
and getClass methods are defined in
the Object class.
- The finalize method is invoked by the garbage collector on an object when
the object becomes garbage. (An object becomes garbage if it is no longer
accessed.) By default the finalize method does nothing; a subclass should
override the finalize method to dispose
of system resources or to perform other cleanup, if necessary.
- We recall that the assignment statement (like newObject
= someObject) cannot be used to copy an object. This statement merely
assigns the reference of someObject
to newObject. To create a new object
with separate memory space, we use the clone()
method: newObject = someObject.clone();.
- NOTE: Not all objects can be cloned. For an object to be cloneable, its
class must implement the java.lang.Cloneable
interface (Ref: 9.4.4).
- The getClass() is used to return the
meta-object of a class
- (When the JVM loads a class (every class must be loaded in order to be
used), it creates an object that contains the information about the class
(such as class name, constructors, and methods.) This object (an instance
of java.lang.Class) is referred to as
a meta-class)
- There is only one meta-object for a class. Every object has a meta-object;
if two objects were created from the same class, their meta objects are
the same.
9 Abstract Classes and Interfaces
- Abstract class: a superclass that is so general that
it cannot have any specific instances
- Multiple inheritance: deriving a subclass from more than
one class. Java does not allow multiple inheritance: Each Java
class must inherit directly from one superclass (i.e. single inheritance).
- Abstract method: a method that cannot be implemented
within an abstract class because its implementation is dependent on the
specific characteristic of the subclass that extends the superclass. An
abstract method is a method signature without implementation. Its implementation
is provided by the subclasses.
- We cannot create instances of abstract classes using the new
operator.
- A class that contains abstract methods must be declared abstract.
- NOTE: An abstract method cannot be contained in a nonabstract class. If
a subclass of an abstract superclass does not implement all the abstract
methods, the subclass must be declared abstract.
- NOTE: An abstract class cannot be instantiated using the new
operator, but we can still defined its constructors, which are invoked in
the constructors of its subclasses.
- NOTE: A class that contains abstract methods must be abstract. However,
it is possible to declare an abstract class that contains no abstract methods.
In this case, as before, we cannot create instances of the class using the
new operator; this class is used as
a base class for defining a new subclass.
- NOTE: A subclass can be abstract even if its superclass is concrete.
- NOTE: A subclass can override a method from its superclass to declare
it abstract. This, albeit being unusual, is useful when the implementation
of the method in the superclass becomes invalid in the subclass. In this
case, the subclass must be declared abstract.
- NOTE: We cannot create an instance from an abstract class using the new
operator, but an abstract class can be used as a data type.
9.4 Interfaces
- An interface is a classlike construct that contains only constants and
abstract methods.
- An interface is, in many ways, like an abstract class--except that an
abstract class can contain variables and concrete methods as well as constants
and abstract methods.
- To distinguish between an interface and a class, we declare an interface
thus:
modifier interface InterfaceName
{
/** Constant declarations */
/** Method signatures */
}
- (An interface is treated like a special case in Java.) Each interface
is compiled into a separate bytecode file, just like a regular class.
- As with an abstract class, we cannot create an instance from an interface
using the new operator, but in most
cases we can use an interface more or less the same way we use an abstract
class.
- Suppose we want to design a generic method to find the larger of two objects
(the objects can be students, circles, or cylinders). We can use an interface
to define a generic compareTo method
to use studentID as the key for comparing
students, radius as the key for comparing
circles, and volume as the key for comparing
cylinders.
- Implementing interfaces:
ComparableRectangle extends Rectangle implements Comparable
{
...
}
- An interface provides another form of generic programming; an interface
can be used the same way as an abstract class, but defining an interface
is difficult from defining an abstract class.
- In an interface, the data must be constants; an abstract class can have
non-constant data fields.
- Each method in an interface has only a signature without implementation;
an abstract class can have concrete methods.
- NOTE: All data fields are public final static
and all methods are public abstract
in an interface. For this reason, these modifiers can be omitted.
- A constant defined in an interface can be assessed using the syntax InterfaceName.CONSTANT_NAME
(e.g. T2.K)
- Java allows only single inheritance for class extension, but multiple
extensions for interfaces. E.g.:
public class NewClass extends BaseClass
implements Interfacei, ..., InterfaceN
{
...
}
- An interface can inherit other interfaces using the extends
keyword. Such an interface is called a subinterface.
- An interface can only extend other interfaces, not classes. A class can
extend its superclass and implement multiple interfaces.
- Unlike the Object class for classes,
interfaces do not have a single root. However, like a class, an interface
defines a type: a variation of an interface type can reference any instance
of the class the implements the interface.
- How do we decide whether to use an interface or a class?
In general, a strong is-a relationship that clearly describes a
parent-child relationship should be modeled using classes. A weak is-a
relationship (aka is-kind-of relationship) indicates that
an object possesses a certain property and should be modeled using an interface.
(E.g. all strings are comparable, so the String class implements the Comparable
interface).
- We can also use interfaces to circumvent the single inheritance restriction
in Java is multiple inheritance is desired: in this case, we design one
as a superclass, and others as interfaces.
- Consider an Edible Interface:
public interface Edible
{
public String howToEat();
}
- and a class called Animal and its
subclasses Tiger, Chicken,
and Elephant. (Since Chicken is edible,
we implement the Edible interface for
the Chicken class:
class Animal
{
class Chicken extends Animal implements Edible
{
public String howToEat()
{
return "Fry it";
}
}
- and now, a class named Fruit and its
subclasses Apple and Orange.
(Since all fruits are edible, we implement the Edible
interface for the Fruit class; in the
Fruit class, we give a generic implementation
of the howToEat method. In the Apple
class and the Orange class, we give
specific implementation of the howToEat
method):
class Fruit implements Edible
{
public String howToEat()
{
return "Eat it fresh";
}
}
class Apple extends Fruit
{
public String howToEat()
{
return "Make apple cider";
}
}
class Orange extends Fruit
{
public String howToEat()
{
return "Make orange juice";
}
}
- The Cloneable Interface, java.lang.Cloneable,
unlike other interfaces that contain constants and abstract methods, is
empty:
package java.lang;
public interface Cloneable {
}
- An interface with an empty body is called a marker interface.
It is used to denote that a class possesses certain desirable properties.
A class that implements the Cloneable
interface is marked cloneable and its objects can be cloned using the clone()
method defined in the Object class.
- Many classes (including Date and Calender)
in the Java library implement Cloneable,
and hence, the instances of these classes can be cloned.
Calender calender = new GregorianCalender(2005, 3, 2);
calender calenderCopy = (Calender)calender.clone();
- To declare a custom class that implements the Cloneable
interface, the class must override the clone()
method in the Object class.
- Java offers a way to incorporate, or wrap, primitive data types into an
object. The corresponding class is called a wrapper class.
(E.g. the int type can be wrapped in
the Integer class, the double
type can be wrapped in the Double class,
etc.) Using a wrapper object instead of a primitive type variable allows
us to take advantage of genetic programming.
- (Each numeric wrapper (Double, Float,
Long, Integer,
Short, and Byte)
extends the abstract Number class, which
contains methods doubleValue(), floatValue(),
intValue(), longValue(),
shortValue(), and byteValue().
These methods "convert" objects into primitive type values.
10 Object-Oriented Modeling
Relationships Among Classes
- Association is a general binary relationship that describes
an activity between two classes. (E.g. students takes a course, or faculty
teaches a course.)
- Each class involved in an association may specify a multiplicity.
A multiplicity could be a number or an interval that specified how many
objects of the class are involved in the relationship.
- An association is usually represented as a data field in the class.
- Aggregation is a special form of association that represents
an ownership relationship between two classes. Aggregation models has-a
relationships. An object may be owned by several other aggregated objects.
- If an object is exclusively owned by an aggregated object, the relationship
between the object and its aggregated object is referred to as composition.
- (E.g.: "A person has a name" is a composition relationship between
the Person class and the Name
class, whereas "a person has an address" is an aggregation relationship
betweent he Person class and the Address
class, since an address may be shared by several persons.
- An aggregation relationship is usually represented as a data field in
the aggregated class (the Person class
in our example).
- Inheritance models the is-a relationship between
two classes. A strong is-a relationship describes a direct inheritance
relationship between two classes. A weak is-a relationship describes that
a class has certain properties. E.g. strong is-a relationship: "Faculty
is a person"; hence:
public class Faculty extends Person {
...
}
- A weak is-a relationship can be represented using interfaces.
E.g. the "students are comparable based on their grades" relationship
can be represented by implementing the Comparable
interface, hence:
public class Student extends Person implements Comparable
{
/** Data fields, Constructors, and Methods */
/** Implement the compareTo method */
public int compareTo(Object object)
{
...
}
}
11 GUI Programming
...
Three basic layout managers:
- FlowLayout
- simplest layout manager: components arranged in the container from
left to right in the order in which they were added; when one row is
filled, another is started. We can specify the alignment of the components
by using one of three constants: FlowLayout.RIGHT, FlowLayout.CENTER,
FlowLayout.LEFT. We can also specify the gap betweent the components
in pixels.
- GridLayout
- BorderLayout