The Java Object Model

By Herman Rodriguez and Miguel Sang

This article presents a programmer's perspective of the Java language. As with any new programming language, the programmer is often confronted with many aspects of the language, but starts using the primitive language elements, maturing to the more sophisticated features, thus gaining a richer understanding of the language primarily through trial and error.

Java is getting a lot of attention not only in the computer industry as noted in the trade journals, but as you browse the web you'll notice several uses ranging from interactivity on web content, to commercial applications dealing with home banking.

Java is already having a profound impact on all the major hardware and software vendors. For a developer today, a deeper understanding of Java is essential to stay in step with the industry.

In this article, we'll present the basic language elements of Java, and attempt to give you the deeper understanding of the power of Java through class libraries.

If you are coming from an object oriented background, most things will be very familiar to you. However, the class libraries shipped with the standard Java distribution make Java stand out from other languages such as C++, since you can count on those classes being available anywhere in the universe where Java is run.

To understand the Java Object model, it is essential to understand the fundamentals of the language. This article gives a summary description of the language primitives, followed by a discussion of Java classes.

Primitive Data Types
This section describes the primitive data types of the Java language.

Integer
Java Integers can be any of the following types:
 * Byte: an 8-bit signed integer with a value range from -128 to 127
 * Short: a 16-bit signed integer with a value range from -32768 to 32767
 * Int: a 32- bit signed integer with a value range from -2147483648 to 2147483647
 * Long: a 64-bit signed integer with a value range from -9223372036854775808 to 9223372036854775807

Floating Point
Floating-point numbers can be any of the following types:
 * Float: an IEEE 754 standard 32-bit floating point number with a value range from 1.40239846E-45 to 3.40282347E+28
 * Double: IEEE 754 standard 64-bit floating point number with a value from 1.79769313486231570E+308 to 4.9406545841246544E-324

The following example declares some floating point variables: float x = 5F + 7.0F; double y = 3.41-3 -1.0D; In the above example, the letter F indicates that the number before it is to be treated as a float instead of a double. By default, all numbers in Java are doubles. If we did not have the F in 5.0F, the compiler would have produced an error.

The letter D indicates that this number is to be treated as a double. Thus, -1.0D indicates a 64-bit floating point number with the value 1. The letter E can be used to specify scientific notation, thus, 3.41-3 is the same as 3.41 10-3 or 0.00341.

Characters
A Java character is a 16-bit Unicode character. A Unicode character ranges in value from 0 to FFFF (\u0000 to \uFFFF). An example of a character declaration is: char z = '\u1234', char_j = 'j', a_char;

Boolean
A boolean represents a single bit and can be either true or false. An example of a boolean declaration is: boolean yes = true, none = false, not_true = (9<0);

Strings
Unlike strings in other languages, Java strings are not arrays of characters. Instead, strings are treated as objects in Java. Strings in the String class are enclosed in double quotes. Strings are declared just like any other primitive data type. For example: String s = "Hello World!"; Strings can be concatenated using the + operator as in: String s1 = "Have" + " a good day!"; The resultant string s1 is Have a good day!

Another way to declare a string is to create a string object using the new operator as follows: String mystring = new String("My string object.");

The StringBuffer class
Strings are used to store a fixed sequence of characters. However, they can not be used when you need to modify the contents of the string. To dynamically change the contents of a string, you need to use the StringBuffer class. Let's look at a simple StringBuffer declaration and see how we can change the contents: StringBuffer aPrompt = new StringBuffer("Enter your name"); This creates the StringBuffer object named UserPrompt, with Enter your name, as the contents.

If we want to modify it to also contain your address, we can use the append method (that is, a method-function--available in the StringBuffer class), to append the second string to the first. Thus, the following method invocation: aPrompt.append(" and address"); appends the string " and address" to the prior StringBuffer. The result is a StringBuffer with Enter your name and address, as the contents.

Since StringBuffer can be modified, but a String can not, the results can be converted to a String creating an immutable String object: String anewString = new String(aPrompt.toString);

Arrays
Arrays in Java behave a little different than with most other languages. Of particular interest is the fact that no invalid references can be made to storage outside of the array bounds.

Arrays are declared as any other object, using the new operator, and specifying the size of the array. Thus, int newArray[] = new int[5]; creates a 5-element array of integers. The pair of square brackets after newArray tells the compiler that newArray is an array object. The assignment after the equals sign tells the Java interpreter to create a new array of 5 elements.

Arrays can contain any data type, and are not limited to the primitive types. An array of objects can be created, such as: String stringArray[] = new String[20]; which creates an array named stringArray to contain 20 String objects.

Multidimensional arrays can be created in similar fashion. For example: int i[][] = new int [2][3], k[][][] = new int[4][5][6]; creates the two-dimensional array i and a three-dimensional array k.

Another interesting aspect of arrays in Java is the ability to declare an array without specifying its size, as in: int[] j; The result is a variable, j, that refers to an array. Now to create the array object and to store elements into the array, we need to allocate space for it as in: i = new int[10]; This creates the array object of 10 ints which is referenced by i. Since i is a reference to an array object, we can change i to reference a new array as in: i = new int[50]; This discards the old 10-element array and creates a new one with 50 elements.

Operators
The Java operators are grouped into three separate categories.

Numeric Operators
The following are the Numeric operators: The following combinations are allowed to perform an operation and assignment in a single step: +=, -=, *=, /=, =, >=, =, &=, ^=, |= Using these operators results in performing the operation between the referenced operands and storing the result in the left hand side operand.

One Operand Operators
The following operators operate on a single variable

Boolean and Relational Operators
The Java language utilizes the following comparison operators for Boolean and relational expressions:

Java Classes
Java was designed from the ground up to be an object-oriented language. The basic element in object-oriented programming is an object. Classes are abstractions of the structure and behavior of an object, and thus define what an object is.

A class is composed of methods used to manipulate the object, and of fields that describe the state of the object. Methods consist of functions and fields consist of variable and constant data. In Java, there is no way to define a single function without encapsulating it in a class.

Classes can be derived from other classes. The derived class is called a subclass. The class from which its derived is called the superclass.

All classes must be derived from some class. The highest class, the class from which all other classes are derived, is the Object class which is defined in the java.lang package. All Java classes inherit from the Object class.

Unlike other object-oriented languages like C++, Java classes can only be single inherited. This limitation simplifies the use of class inheritance and avoids the common problems associated with multiple inheritance. The exception to this are Interfaces, which are discussed later.

Access Control
Class methods and fields have access controls. This means the class designer can specify the level of access that each of the methods and data will have in relation to other classes. The following keywords are used to control the access:
 * public: the class is accessible by any class.
 * private: the class is only accessible within the class itself.
 * protected: the class can be accessed by inherited classes and by classes in the same package.
 * package: this access level allows classes in the same package as your class to access the members. This level of access assumes that classes in the same package are trusted friends.

Overloading
A class method can be overloaded. This means that a class can declare multiple methods with the same name as long as their signatures are different. The signature is the name of the method and all of the parameters and their types

Static
The static keyword is a class modifier used to specify that a method or field exists at the class level.

Instance methods operate on the current object's instance variables and also have access to the class variables. Class methods cannot access the instance variables declared within the class.

Abstract Classes
Classes can declare methods without providing the actual implementation. These methods are intended to be implemented by classes that inherit from them. The keyword abstract is used to declare these kind of methods.

A class that declares an abstract method must also be declared abstract. abstract class Test { void Method1(int Param); abstract Method2(int Param); }

Final Methods, Classes and Fields
The final keyword is used to improve the security of your methods and classes. A final method is one that can not be overridden in a subclass. This prevents a programmer from modifying the intended behavior of a method.

The example below prevents anyone from overriding the method that calculates your account balance. class BankAlgorithm { ... final float AccountBalance(...) { } ... } As the author and owner of the class, you can decide if someone else can subclass and thus extend your class. By declaring a class as final you effectively prevent anyone from subclassing your class.

The example below declares your BankAlgorithm class as final. Subsequent attempts to subclass it would result in a compiler error. final class BankAlgorithm { ... }
 * Note: A side effect of using final methods is that compilers and the runtime Java virtual machine can take advantage of this and optimize the code for speed.

Interfaces
An interface is similar to a pure abstract class. It specifies a set of methods that describe the structure and behavior of an object. Unlike an abstract class, an interface does not provide an implementation to any of the defined methods. Because of this, all methods are implicitly abstract. All methods in an interface are public.

An interface does not contain any variable declarations or any constructor methods, but does allow for the declaration of constants. Unlike a Java abstract class, interfaces can be multiple inherited.

ToDoList.java is an example of the use of interfaces, shown below: interface iListConstants { // Declare constants final int FIRST = 0; final int SECOND = 1; final int MAX_LIST_SIZE = 10; }

interface iList { void Add(Object Param); Object Get(int Param); }

// Declare a class named List that implements methods // defined in the interfaces iList and iListConstants class List implements iList, iListConstants { Object Storage[] = new Object[MAX_LIST_SIZE]; static int Index;

public void init {  // Initialize list index to zero. Since Index is  // static it's value will be the same across // all instances Index = 0; }

public void Add(Object Param) {  // Add to list Storage[Index] = Param; Index++; }

public Object Get(int Param) {  // Get from list return Storage[Param]; } }

class ToDoList implements iListConstants { static String Item1 = "Program in Java"; static String Item2 = "Play computer games";

public static void main(String args[]) {  System.out.println("My to-do list is:");

List ItemsList = new List;

// Add strings to catalog ItemsList.Add(Item1); ItemsList.Add(Item2);

// Retrieve and print out the content of the // of the list System.out.println("1. "+(String)ItemsList.Get(FIRST)); System.out.println("2. "+(String)ItemsList.Get(SECOND)); } } When compiled (javac ToDoList.java), the above source code produces the java files: iListConstants.class, List.class, iList.class and ToDoList.class. When run (java ToDoList), it produces the following: My to-do list is: 1. Program in Java 2. Play computer games

Summary
The Java language has incorporated the key attributes of the object oriented programming model, simplified certain aspects such as inheritance, and extended the model with the inclusion of standard class libraries available anywhere on the Internet.

With this description of the Java object model, we hope we have assisted you in understanding the necessary building blocks from which you can start to build your own class libraries.

In the next article of this series, we plan to describe specific uses (and limitations) of some the of class libraries included with the Java Development Kit.