Return to index

Java Basics 1

 

Topics covered include :

  • public static void main(String[] args)
  • Static classes, static methods and static fields
  • Classes and objects (instances)
  • Constructors and the keyword 'new'
  • Methods (including accessor methods)
  • Identifiers, Scope and Order
  • The Java class libraries, or 'API's
  • Code comments

 

Getting Started

Beginners are often confused by the terminology, if not purpose, of method:

public static void main(String[] args) {} 

Basically, it is a method with a name that the Java interpreter will call to get a program started.

It is a public method so that it can be called from outside the class (by the Java interpreter in this case), and it is static - this means it exists before any instances of the class are created and, indeed, that there is only ever one version of it, shared by all instances that may be created.

The static method 'main()' may contain the complete program in the very simplest cases. For example, the following 'Hello World' program:

public class HelloWorld { 
     public static void main(String[] args) { 
          System.out.println("Hello World"); 
     } 
}   

However, most often the main() method creates an instance of the 'main class' when called by the Java interpreter. In effect, it acts as part of the 'boot-up' mechanism.

public class A { 
     ...
     public static void main(String[] args) { 
          new A(); 
     } 
}   

Once method main() has called the constructor of class A, an instance of A will have been created. In the code above there is no explicit constructor (a method that creates an instance) but there is an implicit one - public A()

We could write an explicit constructor ourselves. In it, we can perhaps set an int field to value 10 and print 'hello' to the system console. Notice that constructors have no return specified and that the constructor name is the same as the class name - A, in this case.

public class A { 
     int i; 

 

     // Constructor
     public A() { 
          i=10; 
          System.out.println("hello"); 
     } 

 

     public static void main(String[] args) { 
          new A(); 
     } 
}   

We could keep a reference to our instance of class A, to pass to instances created of other classes.

public class A { 
     int i; 
     static A a; 

 

     public A() { 
          i=10; 
          System.out.println("hello");
     }

 

   private void createB() {
           B b=new B(a); 
     }

 

     public static void main(String[] args) { 
          a=new A(); 
     } 
}   

The method createB(a) can be called only after the constructor A() has completed, otherwise a will be null. If we need to create an instance of class B during the constructor of A, we must use the keyword 'this' (meaning 'this class') to pass a reference to a to b.

public class A {

int i;

static A a;

 

public A() {

i=10;

B b = new B(this);

}

 

public static void main(String[] args) {

a=new A();

}

}

But what happens after method main() has run, and after the constructor A has completed - what then? Well, if the class is not itself or part of a GUI based application or 'applet', nothing else can happen and we should include a close down command - that is, a call to tell the OS that we have finished running. The value 0 in method System.exit() identifies to the OS that this is a 'normal' program termination; other values can indicate various other reasons for termination - that some kind of error occurred.

public class A { 
     int i; 
     A a; 

 

     public A() { 
          i=10; 
          System.out.println("hello"); 
     } 

 

     public static void main(String[] args) { 
          a=new A(); 
          System.exit(0); 
     } 
}  

In the case of a GUI type application or applet, there will be methods that respond to user interaction such as mouse clicks and key presses. This type of program is called 'event driven'. Once the basic GUI has been created and displayed, what happens next is that the program will wait for and respond to user initiated events.

Before leaving public static void main(String[] args), what is the String[] args bit for? Well, it says that this method 'takes' an array of String values as a parameter (primitive or object type passed to a method). Note that parameters are also called 'arguments'. If we have compiled our class A, we can run it at the command prompt (system console window, 'shell' or 'DOS prompt') with

java A

we can pass information to it by appending a variable number of Strings (0 or more); this is why the argument is a array type. For example,

java A Fred


Our program can take account of these arguments. For example:

public class A { 
     public static void main(String[] args) { 
         String s="";
         if (args.length>0) {
              s=args[0];    // the first argument in array args  
         }
         System.out.println("hello" + s); 
     } 
}   

In TJI, there is no need to call the Java interpreter from the command line. However, you can still set run-time arguments for your programs - see the 'Run' menu.

Now that we know how we can get our program running, we can turn our attention to matters of Object Oriented Design, event handling, etc. But first let's look further at the issues surrounding what a class is.

 

Classes and Objects

All programs written in the Java language (Java programs) are built from classes. Classes can be static or one or multiple instances can be created of non-static classes. Classes consist of fields and methods. Fields hold data, 'information', 'state'. Methods allow access to fields or perform processing of data or handle interaction with the user or other objects.

Java source code is stored in .java files and is a natural language like description of what a class should be and do. This is translated to .class files by the compiler (javac). The contents of a .class file is the description of what the class should be and do in a language much closer to the machine language of the computer. The final step of translation is done by the Java Virtual Machine (JVM) which tweaks the machine code to that understood by the actual operating system that the program is to run on - be it Mac, UNIX or Windows.

Thus, a program has to be converted to a form the Java VM can understand so that any computer with a Java VM can interpret and run the program. Compiling a Java program means taking the programmer-readable text in your program file (also called source code) and converting it to 'bytecodes', which are platform-independent instructions for the Java VM.

It is when the class file is loaded into memory by the interpreter of the the JVM (java), that the class file can hold values and its methods run. Non-static classes can be 'instantiated' multiple times and each one has its own state. There is only one copy of a static class. In non-static classes there may be multiple instances but only one copy of any static field or method.

Instances of classes are called 'objects'. To say that 'object a is an instance of class A' is to say that 'object a is of type A'.

If we think of the word 'chair' we have a conceptual understanding of what it is - and this 'schema' is to real chairs as class is to object. The chairs we see around us may differ in color, height etc and this is because these 'fields' that make up their 'state' are different. Chairs are often used with tables - and, further, are both types of 'furniture'. Classes are hierarchically arranged just as furniture or living things are. A child class inherits abilities from it's parent but adds its own speciality.

 

Class Structure 

An application is created from classes. A class is similar to a 'record' in the Pascal language or a 'struct' in the C language in that it stores related data in fields, where the fields can be of different types. So you could, for example, store a text string in one field, an integer in another field, and a floating point in a third field. The difference between a class and a record or struct is that a class also defines the methods to work on the data. It is a self-contained unit having both state and behaviour.

For example, a very simple class might store a string of text and define one method to set the string and another method to get the string and print it to the console. Methods that get and set data are called accessor methods. A class may well contain other methods that perform other kinds of task, such as processing data, contructing a GUI, responding to events, reading a file, etc.

Every application needs one class with a 'main()' method. This class is the entry point for the program, and is the class name passed to the java interpreter to run the application.

The code in the main() method executes first when the program starts.

  public class SimpleProgram { 
        public static void main(String[] args) { 
               System.out.println("I'm a Simple Program"); 
        } 
 } 

The public static void keywords allow the Java Virtual Machine (JVM) interpreter to call the program's main() method to start the program (public) without creating an instance of the class (static), and the program does not return data to the Java VM interpreter (void) when it ends.

An instance of a class is an executable copy of the class. While the class describes the data and behavior, you need to create an instance of the class to acquire and work on the data (one executable version of a static class is automatically created by the interpreter when it is loaded into memory).

The main() method is static to give the Java VM interpreter a way to start the class without creating an instance of the main class first. Instances of the main class can be created within the main() method after the program starts.

The main() method for the SimpleProgram class does not create an instance of the SimpleProgram class because none is needed. The SimpleProgram class has no other methods or fields, so no class instance is needed to access them from the main method. The Java platform lets you execute a class without creating an instance of that class as long as its static methods do not call any non-static methods or fields.

The SimpleProgram class just calls System.out.println(). The java.lang.System class, among other things, has a static out field of type PrintStream that is used to invoke the print() and println() methods in the PrintStream class.

The static fields and methods of a class can be called by another program without creating an instance of the class. So, just as the Java VM interpreter calls the static main() method in the SimpleProgram class without creating an instance of the SimpleProgram class, the SimpleProgram class can call the static println() method in the System class, without creating an instance of the System class.

However, a program must create an instance of a class to access its non-static fields and methods. Accessing static and non-static fields and methods is discussed further with several examples in the next section.

 

Fields and Methods

The ExampleTwo class alters the simple example to store the text string in a static field called text. The text field is static so that its data can be accessed directly by the static call to System.out.println() without creating an instance of the ExampleTwo class first.

 class ExampleTwo { 
      static String text = "I'm a Simple Program"; 

 

      public static void main(String[] args) { 
           System.out.println(text); 
      } 
} 

Next we will add a getText() accessor method to the program to retrieve and print the text.

The Example3 class accesses the static text field with the non-static getText() method. Non-static methods and fields are called 'instance methods' and 'instance fields'. This approach requires that an instance of the Example3 class be created in the main() method. To keep things interesting, this example includes a static text field and a non-static instance method (getStaticText()) to retrieve it. The field and method return values are all of type String.

 public class Example3 { 
     String text = "I'm a Simple Program"; 
     static String text2 = "I'm static text"; 

 

     public String getText() { 
            return text; 
     } 

 

     public String getStaticText() { 
            return text2;  
     } 

 

     public static void main(String[] args) { 
            Example3 progInstance = new Example3(); 
            String retrievedText = progInstance.getText(); 
            String retrievedStaticText = progInstance.getStaticText();  
            System.out.println(retrievedText); 
            System.out.println(retrievedStaticText); 
     } 
} 

The Example4 class accesses the static text field with the static getText method. Static methods and fields are called 'class methods' and 'class fields'. This approach allows the program to call the static getText() method directly without creating an instance of the Example4 class.

 public class Example4 { 
      static String text = "I'm a Simple Program"; 

 

      // Accessor method 
      public static String getText() { 
            return text; 
      } 

 

      public static void main(String[] args) { 
            String retrievedText = getText(); 
            System.out.println(retrievedText); 
      } 
} 

So, class methods can operate only on class fields, and instance methods can operate on both class and instance fields.

You might wonder what the difference means. In short, there is only one copy of the data stored or set in a class field but each instance has its own copy of the data stored or set in an instance field.

class X {
     static int a=36;
     int b=0;

 

     public static void setFieldA(int i) {
          a=i;
     }
   
     public void setFieldB(int i) {
          b=i;
     }
} 

Now suppose that we create 3 instances of class X. Initially, all 3 instances will have the same state :

A : 36
B = 0
A : 36
B = 0
A : 36
B = 0

After we call the following methods on instance 1

  • setFieldA(50)
  • setFieldB(25)

the instances will have the following state:

A : 50
B = 25
A : 50
B = 0
A : 50
B = 0

A now has the value 50 in all 3 instances because A is a class field (it is static). Field B is now 25 in instance 1 but remains 0 in the other two instances, as expected.

At runtime, there is only one copy of the value for static Field A and each instance points to the one copy. When setFieldA(50) is called on the first instance, the value of the one copy changes from 36 to 50 and all three instances point to the new value. But, when setFieldB(25) is called on the first instance, the value for Field B changes from 0 to 25 for the first instance only because each instance has its own copy of Field B. So the three class instances share one static field and have one instance field each.

Remember - static methods and fields are sometimes called 'class methods' and 'class fields', and non-static methods and fields are sometimes called 'instance methods' and 'instance fields'.

 

Constructors

Classes have a special method called a constructor that is called when a class instance is created. There can be more than one. A constructor always has the same name as the class and no return type. The Example5 class uses a constructor to initialize the text string.

If you do not write your own constructor, the compiler adds a no-parameters default constructor, which in turn calls the no-parameters constructor of the parent class. The default constructor initializes all non-initialized fields and variables to null, false or zero as appropriate.

 public class Example5 { 
      String text; 

 

      // Constructor 
      Example5() { 
           text = "I'm a Simple Program"; 
      } 

 

      // Accessor method 
      public String getText() { 
            return text; 
      } 

 

      public static void main(String[] args) { 
            Example5 progInst = new Example5(); 
            String retrievedText = progInst.getText(); 
            System.out.println(retrievedText); 
      } 
} 

A simple program that prints a short text string to the console would probably do everything in the main() method and not use the constructor, text field, and getText() method. However, this very simple program is a useful way to demonstrate the structure and elements in a basic Java program.

One key to good program design is to divide long methods into several shorter ones that are as generic (and hence reusable) as possible. In this way, besides reusability comes maintainability, brevity and robustness. As a guide, consider that a method should do just one step. If a method does several steps of a task, consider dividing it into several methods.

Finally, note that classes can have more than one constructor. Example6 adapts Example5 by adding a second alternative constructor that allows the text field to be initialised to the specified value.

 public class Example6 { 
      String text; 

 

      // Constructor 
      Example6() { 
           text = "I'm a Simple Program"; 
      }

 

      // Alternative Constructor 
      Example6(String s) { 
           text = s; 
      }

 

      // Accessor method 
      public String getText() { 
            return text; 
      } 

 

      public static void main(String[] args) { 
            Example6 progInst = new Example6(); 
            String retrievedText = progInst.getText(); 
            System.out.println(retrievedText); 
      } 
} 

 

Identifiers, Scope and Order

In the statement :

Apple apple1=new Apple();

the variable named apple1 is declared to be of data type Apple. A variable name (such as apple1) is called an identifier. Identifiers must begin with an underscore or character; numbers can also be used after the first character. Identifiers are case sensitive and obviously must be different from any of Java's 'reserved' words (those words that make up the java language, such as 'if').

When we say "apple1 is an instance of class Apple" we mean "apple1 is a reference to an instance of class Apple".

The order of methods is not important. However, an identifier must be defined before it is used. This means that the statement defining it must occur before we attempt to use it.

public int add(int x, int y) { 
     z=x+y; 
     int z; 
     return z; 
} 

will not compile because identifier z has not been defined before we attempt to use it.

public int multiply(int x, int y) { 
     if ((x==0) || (y==0)) { 
          return 0; 
     } else { 
          int z=x * y; 
     } 
     return z; 
}  

Nor will the above method - beacuse of 'scope'. An identifier is known after being declared within it's own code 'block' and all child blocks only. A 'block' is all the statements between '{' and '}'. When variable goes out of scope, it is no longer known - the compiler will complain if you try to use a variable out of scope. At run-time, when a variable goes out of scope, the memory it used is marked as free and awaits automatic recovery, to be used for something else.

Below is a corrected version of the method.

public int multiply(int x, int y) { 
     int z=0;
     if ((x==0) || (y==0)) { 
          return 0; 
     } else { 
          z=x * y; 
     } 
     return z; 
}  

In fact, this method can be shortened to :

public int multiply(int x, int y) { 
     int z=0;
     if ((x!=0) && (y!=0)) { 
          z=x * y; 
     } 
     return z; 
}

The 'Java Platform'

The Java platform consists of the Java application programming interfaces (APIs) and the Java Virtual Machine (JVM).

The Java APIs are libraries of compiled code that you can use in your programs. They let you add ready-made and customizable functionality to save you programming time. You can both use and extend the classes defined there.

The simple programs in this document have used a Java API - class System in package java.lang - to print a line of text to the console. The console printing capability is provided in the API ready for you to use; you simply supply the text to be printed.

Java programs are run (or 'interpreted') by another program called the Java VM. If you are familiar with Visual Basic or another interpreted language, this concept is probably familiar to you. Rather than running directly on the native operating system, the program is interpreted by the Java VM for the native operating system. This means that any computer system with the Java VM installed can run Java programs regardless of the computer system on which the applications were originally developed.

For example, a Java program developed on a Personal Computer (PC) with the Windows NT operating system should run equally well without modification on a Sun Ultra workstation with the Solaris operating system, and vice versa.

 

Code Comments

Code comments are placed in source files to describe what is happening in the code to someone who might be reading the file (and that includes yourself!), to comment-out lines of code to isolate the source of a problem for debugging purposes, or to generate API documentation. To these ends, the Java language supports three kinds of comments: double slashes, C-style, and 'doc comments'.


Double Slashes

Double slashes ( //... ) are also used in the C++ programming language, and tell the compiler to treat everything from the slashes to the end of the line as text.

// A Very Simple Example :
public class ExampleProgram { 
     public static void main(String[] args) { 
          System.out.println("I'm a Simple Program"); 
     } 
}   

C-Style Comments

Instead of double slashes, you can use C-style comments ( /*...*/ ) to enclose one or more lines of code to be treated as non source code text.

/*  
This is a C-style comment
*/ 
class ExampleProgram { 
     public static void main(String[] args) { 
          System.out.println("I'm a Simple Program"); 
     } 
}  

Doc Comments

To help generate documentation for your program, you can use 'doc comments' ( /** ... */ ) to enclose lines of text for the javadoc tool to find. Notice the double asterisk at the start. The SDK's javadoc tool locates the doc comments embedded in source files and uses those comments to help generate API documentation. TJI's simpler, and much faster, project documentation tool uses doc-comments in the same way. A doc-comment should immediately precede the class or method it describes.

/**
* This class displays a text string at the console. 
*/ 
public class ExampleProgram { 

 

     /**
     * In this method we print a message to the console.
     */
     public static void main(String[] args) { 
          System.out.println("I'm a Simple Program"); 
     } 
}  

With one simple class, there is little reason to generate API documentation. However, API documentation makes good sense when you have an application made up of a number of complex classes that need documentation - particularly if the source code is to be shared with others; or, indeed, if the class files are to be used by others (as with the standard Java library APIs). The javadoc tool generates HTML files (Web pages) that describe the class structures, fields and methods, together with the additional notes contained in the doc comments. TJI's project documentation tool works in a very similar way to JavaDoc and is much faster.

In TJI, the project documentation tool can be run simply by selecting the 'Doc.s' tab (or by selecting 'Show Project Documentation' from the 'Options' menu if it is not already showing). The documentation files are stored in a subdirectory of the source directory called docs.

 

The Java API Documentation

The Java SDK installation usually includes the API documentation, which describes the APIs available for you to use in your programs. The files are stored in subdirectory docs/api. For example, if the Java platform is installed in /usr/local/java/jdk1.4, then the API documentation will be found in directory /usr/local/java/jdk1.4/docs/api . In TJI, the API documentation is readily available in a custom fast access form in the 'Guru' tab.

If for some reason you have the API documentation installed in a different directory, you can set this from the 'Options' menu of the 'Main' tab; TJI will remember this setting.

If you do not have the API documentation installed, you can download it from Sun's Java site at http://java.sun.com Remember to set the documentation path in TJI once you have it installed ('Default Settings' in the 'Options' menu) - it will greatly assist you in your Java Programming.

 

Download and run ...

An improved version of the example program is available for download as a TJI project on our web site - in the 'Resources' page.

Simply download the zip file and then choose 'Project Import' from the 'Project' menu. Select the zip file and the project will be imported and setup automatically. Now simply click on the 'Run' button to compile and run the example.

 

Note : Some parts of this document (and Java Basics 2 and 3) were based on 'Essentials of the Java Programming Language' - a book by Monica Pawlan, also on-line at Sun's java site.

Return to index