Chapter 1: Java Basics

1.1: Why Java

This section was quoted from the lecture note written by Monash University lecturer Mr. Matt Mitchell.

Java has the following features:

** Simple

Java is designed to be similar to and simpler to C/C++. It eliminates the following troublesome features of C/C++:

** Distributed

Java's network programming facilities are one of the language's best features.

** Interpreted

Source code is initially compiled (javac) into architecture-neutral byte-codes. Byte-codes are interpreted by Java virtual machine (JVM) provided by java or Netscape with a seamless linking stage. However, JIT compilers lead to a large performance increase in compilation and runtime execution.

** Robust

** Secure

** Architecture-neutral

** Portable

** Performance not bad

** Multithreaded

** Dynamic

1.2: The Use of Type

There are two forms of types in Java: class and interface. Type has two roles:

  1. At compiling time, used by the compiler to check whether a method call to an object can be understood by that object
  2. At run time, used as a mould to make new instances of this type

1.3: Polymorphism and Dynamic Binding

The process used by OO programming languages to implement polymorphism is called dynamic binding. C++ require you to use a special keyword virtual to enable dynamic binding, but Java doesn't require any keyword. All functions are by default dynamically bound.

1.4: Abstract Base Class (ABC)

Unlike C++, in which if you want to have an ABC you have to achieve it by making at least one method pure, in Java you can have an ABC without any method being abstract. Keyword abstract must be used in front of an abstract class or method.

An abstract method can only be created inside an abstract class. If you do not declare the class with an abstract method abstract, compiler will complain.

Just like C++, when an abstract class is inherited, all its abstract methods must be implemented, otherwise the inherited class becomes abstract as well and compiler will complain that you did not put keyword abstract in front of it.

Keyword interface takes one step forward by preventing any implementation. This forces the separation of interfaces and implementation and thus is very useful. The other advantage of interface is that you can combine many interfaces together, becaue in Java you CAN NOT inherit from more than one class - C++'s multiple inheritance is not allowed in Java.

1.5: Dynamic Memory Allocation

In Java objects except for primitive objects can only be created dynamically in a memory pool called the heap. Time needed for this process is significantly longer than to create storage on the stack (automatic or scoped variables), which is the most efficient way to allocate and free storage for objects. But we assumes that objects tend to be complicated and thus the overhead will not have an important impact. So there will be no "&" or "*" operator in Java.

1.6: Singly-rooted Hierarchy

Ideally, in an OOP language, all classes should ultimately be inherited from one class, which is simply called Object in Java. All objects in a singly rooted hierarchy have an interface in common, so they are ultimately the same type. This guarantees that all objects have certain common basic functionality and facilitates generic polymorphism across all objects.

A singly-rooted hierarchy along with all objects created on the heap, greatly simplifies argument passing, which is quite a complex issue in C++. You can receive any object with an Object handle, while in C++ you have to know at least the base class of the coming object. On the other hand, since run-time type information (RTTI) is guaranteed to be in all objects, you will never have an object with unknown type.

The reason C++ didn't choose this advantage is that a singly-rooted hierarchy puts restrains on your program design, particularly on the use of existing C code.

1.7: Clean Up Objects

When there are more than one programs using one object, it may be complex to decide when to delete an object. In Java, the garbage collector is designed to take care of releasing the memory. It knows when to delete the objects. This feature, together with the singly-rooted hierarchy and the fact that all objects are created from memory heap, make programming in Java much simpler than in C++ - you have far fewer decisions to make and hurdles to overcome. There is no memory leak in Java.

The price for all these programming convenience is run-time overhead. In addition to the dynamic memory allocation which takes more overhead, garbage collector is also a concern. It only starts when it feels the shortage of memory. You never know when it will start and how long it will take. So there is an inconsistency in the executing speed of Java program, and you can not use it for real-time programs in which the execution speed is critical.

If you want something except for memory releasing to be done at a proper time, you must provide your own method with arbitrary name, and call it yourself. Java does not provide enforced or standard method like C++ destructor.

1.8: Passing String Array to main( ) at Command Line

Unlike C++, Java's main( ) has a String array argument. Therefore, you can pass a sequence of Strings to main at the command line when starting the program:

   
   public class Test {
      public static void main(String [] s)
      {
          System.out.println("The string's length is: " + s. length + "\n");
          for(int i = 0; i < s. length; i++)
              System.out.println(s[i] + "  ");
      }
   }

If you type at the DOS command line

   
   C:\Mydocu\Java\java Test 111 222 333 444 555

The output will be:

   
   The string's length is: 5
   111  222  333  444  555

1.9: Good Software Engineering: Do Not Modify the Arguments

To the reader of your code, the arguments passed in a method call are usually information provide to the method, they shouldn't be modified by the method. A method should only modify its own object, not the argument objects passed from outside. This practice makes your code easier to read and understand.

1.10: Scope of Objects

Just like in C++, scope is defined with { }. In Java you can not have two objects with the same name in different scopes. The designer of Java considers it to be confusing:

   
   {  int x = 1;
      {  int x = 2;  } // not allowed in Java
   }

1.11: No need for Forward Declaration

In C++, if the invoking of a class or function is before the definition, you have to put a forward declaration before the invoking point. In Java you needn't do this. So long as the definition is in the same code file you can invoke it anywhere.

1.12: Importing Packages

In C++ classes and independent functions are grouped in libraries. In Java, classes are grouped in packages.

In C++ you can use "#include" to import a whole library, but you can't just import one class in a library. In Java you can either import a single class in a package by saying:

   
   import java.util.Vector;  // Vector is a class

or import all classes in a package:

   
   import java.util.* ;

All classes automatically have access to package java.lang. So there is no need to import from it.

1.13: static Class Members

When we say that a class member is static, it means that it is not tied to a particular object of its type. It exists before any object of that class is created. It stays one copy per class regardless of the number of objects created from that class.

If you consider the nature of class methods, you will find that they are in fact all static members - there is only one copy of the methods regardless of how many instances of that class have been created, and they are not tied to any particular object.

Therefore, the difference between a static method and a non-static method is: when a non-static method is called, e.g., method "set" of object "o1" of class "Test" is called - "o1.set(33)", the call is implicitly converted by the compiler to "Test.set(o1, 33)" - the handle of the specific object is implicitly passed to the method as the first argument. When a static method is called, no object handle is passed.

For this reason, a static method can not access any non-static data or method - because they are all tied to a certain object and the method does not have the handle of any object - unless we explicitly pass the object handle to the static method, as the compiler explicitly does to static method calls.

There are two ways of referring to a static members or functions.

  1. Through object name, the same way to refer to usual members and methods
  2. Through class name
   
   Person.total1++;
   Person.list1();

The static data members of a base class are not duplicated in its derived class.

1.14: Java Comments

There are two types of comments in Java as in C++: anything between /* and */ or one line after //. However, if you want Javadoc to automatically collect the comment into the Html file it generates, you have to put the comment in exactly the following format before the class, a field or a method:

   
   /**
   _* <p>This class does the following things:</p>
   _* <ol>
   _* <li>Acquire a Socket connection from the client;
   _* <li>Read in the first line which is the client request line;
   _* <li>Analyze the request line and initialize all the fields with parameters
   _* contained in the request line.
   _* </ol>
   _*/

Here space is represented by "_". Notice that all Html tags are applicable in the comment.

1.15: Overflow - No Run-Time Exceptions

When you multiply two big integers, the result may overflow. You will get no compiling errors or run-time exceptions - only the result is wrong.

1.16: Random Number Generation

There are two kinds of random numbers in Java: float and integer number:

   
   import java.util.*;
   
   class Test {
      static void main(String argu[])
      {
         Random r1 = new Random();   
         for(int i = 0; i < 3; i++)
         {
            System.out.println("Integer: " + r1.nextInt() +
            ",  float: " + Math.random());
         }
      }
   }

Output will be:

   Integer: -1320465790,  float: 0.692555100401038
   Integer:  194646209,   float: 0.8077478654382154
   Integer: -825716618,   float: 0.4479063911209129

From the sample code you can see that

1) Class Random has a non-static method nextInt( ) which returns an integer between a very big negative and positive constant. To make use of it you may have to use modulus operator % and Math.abs( ).

2) Class Math has a STATIC method random( ) which returns a float between 0 and 1 - including 0 but not including 1.

1.17: Compilation Unit

In Java a source code file is called a compilation unit or sometimes a translation unit.

1.18: Factory Method

If you want to make sure that only one object of a class is created:

   
   public class Test {
      private Test() {}
      private static Test t1 = new Test();
   
      public static Test create()
      {
         return t1;
      }
   }

Here you must have that empty private default constructor, because if you don't write one here, the compiler will automatically create a public one for you.