Basics of Java

This post is a review of fundamental Java and programming concepts.

Java Class Structure

A Java class is described in a text file with a .java extension. In the example shown below, the Java keywords are highlighted in bold.

package [package_name];
import [other_packages];

public class ClassName {
     [variables(also known as fields)];
     [constructor(s)];
     [other methods];
}
  • The package keyword defines where this class lives relative to other classes, and provides a level of access control. You use access modifiers (such as public and private) later in this lesson.
  • The import keyword defines other classes or groups of classes that you are using in your class. The import statement helps to narrow what the compiler needs to look for when resolving class names used in this class.
  • The class keyword precedes the name of this class. The name of the class and the file name must match when the class is declared public (which is a good practice). However, the keyword public in front of the class keyword is a modifier and is not required.
  • Variables, or the data associated with programs (such as integers, strings, arrays, and references to other objects), are called instance fields (often shortened to fields).
  • Constructors are functions called during the creation (instantiation) of an object (a representation in memory of a Java class).
  • Methods are functions that can be performed on an object. They are also referred to as instance methods.

A Simple Class

To run a Java program, you must define a main method in the Java class as shown in below example. The main method is automatically called when the class is called from the command line.

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

Command-line arguments are passed to the program through the args[] array.

Note: A method that is modified with the keyword static is invoked without a reference to a particular object. The class name is used instead. These methods are referred to as class methods. The main method is a special method that is invoked when this class is run by using the Java runtime.

Java Naming Conventions

  • Class names should be nouns in mixed case, with the first letter uppercase and the first letter of each internal word capitalized. This approach is termed “upper camel case.”
  • Methods should be verbs in mixed case, with the first letter lowercase and the first letter of each internal word capitalized. This is termed “lower camel case.”
  • Variable names should be short but meaningful. The choice of a variable name should be mnemonic: designed to indicate to the casual observer the intent of its use.
  • One-character variable names should be avoided except as temporary “throwaway” variables.
  • Constants should be declared by using all uppercase letters.
Note: The keyword final is used to declare a variable whose value may only be assigned once. Once a final variable has been assigned, it always contains the same value.

How to Compile and Run

Java class files must be compiled before running them. To compile a Java source file, use the Java compiler (javac).

$ javac –cp [path to other classes] -d [compiler output path] [path to source].java

You can use the CLASSPATH environment variable to the directory above the location of the package hierarchy. After compiling the source .java file, a .class file is generated. To run the Java application, run it using the Java interpreter (java):

$ java –cp [path to other classes] [package name].[classname]

CLASSPATH

The default value of the classpath is the current working directory (.); however, specifying the CLASSPATH variable or the –cp command line switch overrides this value.

The CLASSPATH variable is used by both the Java compiler and the Java interpreter (runtime).

The classpath can include:

  • A list of directory names (separated by semicolons in Windows and colons in UNIX) – The classes are in a package tree relative to any of the directories on the list.
  • A .zip or .jar file name that is fully qualified with its pathname – The classes in these files must be zipped with the pathnames that are derived from the directories formed by their package names.
Note: The directory containing the root name of the package tree must be added to the classpath. Consider putting classpath information in the command window or even in the Java command, rather than hard-coding it in the environment.

How to Compile and Run: Example

Consider the following simple class in a file named HelloWorld.java in the test directory in the path /home/oracle:

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

Compile the HelloWorld.java program using below command:

$ javac HelloWorld.java

To run the application, you use the interpreter and the class name:

$ java HelloWorld
Hello World

The advantage of an IDE like NetBeans is that management of the class path, compilation, and running the Java application are handled through the tool.

Code Blocks

Java fields (variables) and methods have a class scope defined by the opening left curly brace and ending at the closing right curly brace. Class scope allows any method in the class to call or invoke any other method in the class. Class scope also allows any method to access any field in the class.

For example:

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

Code blocks are always defined by using braces {}. A block is executed by executing each of the statements defined within the block in order from first to last (left to right).

The Java compiler discards unnecessary white space in a line of code. Line indentation is not required but makes the code much more readable. In this post, the line indentation is four spaces, which is the default line indentation used by the NetBeans IDE.

Primitive Data Types

Integer

Java provides four different integer types to accommodate different size numbers. All the numeric types are signed, which means that they can hold positive or negative numbers.

The integer types have the following ranges:

  • byte range is –128 to +127. Number of bits = 8.
  • short range is –32,768 to +32,767. Number of bits = 16.
  • int range is –2,147,483,648 to +2,147,483,647. The most common integer type is int. Number of bits = 32.
  • long range is –9,223,372,036,854,775,808 to +9,223,372,036,854,775,807. Number of bits = 64.

Floating Point

The floating-point types hold numbers with a fractional part and conform to the IEEE 754 standard. There are two types of floating points: float and double.

double is called so because it provides double the precision of float. A float uses 32 bits to store data, whereas a double uses 64 bits.

Numeric Literals

Any number of underscore characters (_) can appear between digits in a numeric field. This can improve the readability of your code.

long creditCardNumber = 1234_5678_9012_3456L;
long socialSecurityNumber = 999_99_9999L;
long hexBytes = 0xFF_EC_DE_5E;
long hexWords = 0xCAFE_BABE;
long maxLong = 0x7fff_ffff_ffff_ffffL;
byte nybbles = 0b0010_0101;
long bytes = 0b11010010_01101001_10010100_10010010;

Rules for Literals

You can place underscores only between digits; you cannot place underscores in the following places:

  • At the beginning or end of a number
  • Adjacent to a decimal point in a floating point literal
  • Prior to an F or L suffix
  • In positions where a string of digits is expected
Note: The Java language is case-sensitive. In Java, the variable creditCardNumber is different from CREDITCARDNUMBER. Convention indicates that Java variables and method names use “lower camel case”―lowercase for the first letter of the first element of a variable name and uppercase for the first letter of subsequent elements.

Operators

Simple assignment operator

= Simple assignment operator

Arithmetic operators

+ Additive operator (also used for String concatenation)
– Subtraction operator
* Multiplication operator
/ Division operator
% Remainder operator

Unary operators

+ Unary plus operator; indicates positive
– Unary minus operator; negates an expression
++ Increment operator; increments a value by 1
-- Decrement operator; decrements a value by 1
! Logical complement operator; inverts the value of a boolean.

Because numbers have been introduced, the above section a list of common operators. Most are common to any programming language, and a description of each is provided. The binary and bitwise operators have been omitted for brevity.

Note: Operators have definitive precedence. Precedence can be overridden using parentheses.

Logical Operators

Equality and relational operators

== Equal to
!= Not equal to
> Greater than
>= Greater than or equal to
< Less than
<= Less than or equal to

Conditional operators

&& Conditional-AND
|| Conditional-OR
?: Ternary (shorthand for if-then-else statement)

Type comparison operator

instanceof Compares an object to a specified type

if else Statement

The example below demonstrates the syntax for an if-else statement in Java.

1 public class IfElse {
2
3    public static void main(String args[]){
4         long a = 1;
5         long b = 2;
6
7         if (a == b){
8            System.out.println("True");
9          } else {
10           System.out.println("False");
11       }
12
13    }
14 }

The else statement provides a secondary path of execution when an if clause evaluates to false. The output from the code above is False.

switch Statement

A switch statement is used to compare the value of a variable with multiple values. For each of these values, you can define a set of statements to execute. The switch statement evaluates its expression, then executes all statements that follow the matching case label. Each break statement terminates the enclosing switch statement. The break statements are necessary because without them, statements in switch blocks fall through: All statements after the matching case label are executed in sequence, regardless of the expression of subsequent case labels, until a break statement is encountered.

1 public class SwitchStringStatement {
2      public static void main(String args[]){
3
4             String color = "Blue";
5             String shirt = " Shirt";
6
7             switch (color){
8                 case "Blue":
9                       shirt = "Blue" + shirt;
10                      break;
11                case "Red":
12                     shirt = "Red" + shirt;
13                      break;
14                default:
15                     shirt = "White" + shirt;
16             }
17
18        System.out.println("Shirt type: " + shirt);
19    }
20 }
Note: Deciding whether to use if-then-else statements or a switch statement is based on readability and the expression that the statement is testing. An if-then-else statement can test expressions based on ranges of values or conditions, whereas a switch statement tests expressions based only on a single integer, character, enumerated value, or String object.

In Java SE 7 and later, you can use a String object in the switch statement’s expression. The code snippet above demonstrates using Strings in the switch statement.

while Loop

The while loop performs a test and continues if the expression evaluates to true.

package com.example.review;
public class WhileTest {
       public static void main(String args[]) {
            int x = 10;
            while (x < 20) {
                 System.out.print("value of x : " + x);
                 x++;
                 System.out.print("\n");
             }
        }
}

The while statement evaluates expression, which must return a boolean value. If the expression evaluates to true, the while statement executes the statements in the while block. The while loop, shown above, iterates through an array by using a counter. The output from the example above:

value of x : 10 
value of x : 11 
value of x : 12 
value of x : 13 
value of x : 14 
value of x : 15 
value of x : 16 
value of x : 17 
value of x : 18 
value of x : 19

There is also a do-while loop, where the test after the expression has run at least once. The difference between do-while and while is that do-while evaluates its expression at the bottom of the loop instead of the top.

for Loop

The for statement provides a compact way to iterate over a range of values – it repeatedly loops until a particular condition is satisfied.

1 public class ForLoop {
2
3       public static void main(String args[]){
4
5         for (int i = 0; i < 9; i++ ){
6                System.out.println("i: " + i);
7          }
8
9     }
10 }

A counter is initialized and incremented for each step of the for loop shown in the example above. When the condition statement evaluates to false (when i is no longer less than 9), the loop exits. Here is the sample output for this program.

i: 0
i: 1
i: 2
i: 3
i: 4
i: 5
i: 6
i: 7
i: 8

Arrays and for-each Loop

This class demonstrates how to define arrays in Java and iterate over arrays by using foreach loop.

1 public class ArrayOperations {
2       public static void main(String args[]){
3
4         String[] names = new String[3];
5
6         names[0] = "Blue Shirt";
7         names[1] = "Red Shirt";
8         names[2] = "Black Shirt";
9
10         int[] numbers = {100, 200, 300};
11
12         for (String name:names){
13             System.out.println("Name: " + name);
14         }
15
16         for (int number:numbers){
17            System.out.println("Number: " + number);
18        }
19     }
20 }

The first array, names, creates a String array and initializes each element separately. The second array, numbers is an array of integers. Each array is iterated through using the Java for-each construct. The enhanced for loop is used to make the for loop more compact and easy to read. It is used to access each successive value in a collection of values. It is commonly used to iterate over an array or a Collections class (for example, an Array or an ArrayList).The output of the class is shown here:

Name: Blue Shirt
Name: Red Shirt
Name: Black Shirt
Number: 100
Number: 200
Number: 300
Note: Arrays are also objects by default. All arrays support the methods of the class Object.You can always obtain the size of an array by using its length field

Strings

The code below demonstrates how text characters are represented in Java.

1 public class Strings {
2
3     public static void main(String args[]){
4
5          char letter = 'a';
6
7          String string1 = "Hello";
8          String string2 = "World";
9          String string3 = "";
10         String dontDoThis = new String ("Bad Practice");
11
12         string3 = string1 + string2; // Concatenate strings
13
14         System.out.println("Output: " + string3 + " " + letter);
15
16       }
17   }

Single characters can be represented with the char type. However, Java also includes a String type for representing multiple characters. Strings can be defined as shown above and combined by using the “+” sign as a concatenation operator.

The output from the code in the slide is:

Output: HelloWorld a

Caution: The String class is immutable: After being created, the contents of an object of the class String can never be modified. The immutability of String objects helps the JVM to reuse String objects, reducing memory overhead and improving performance.

Strings should always be initialized by using the assignment operator “=” and text in quotation marks, as shown in the examples. The use of new to initialize a String is strongly discouraged. The reason is that “Bad Practice” in line 10 is a String literal of type String. Using the new keyword simply creates another instance functionally identical to the literal. If this statement appeared inside of a loop that was frequently invoked, a lot of needless String instances could be created.

String Operations: StringBuilder

The example below demonstrates usage of the StringBufilder class and commonly used methods.

public class StringOperations {
     public static void main(String arg[]) {
            StringBuilder sb = new StringBuilder("hello");
            System.out.println("string sb: " + sb);
            sb.append(" world");
            System.out.println("string sb: " + sb);

            sb.append("!").append(" are").append(" you?");
            System.out.println("string sb: " + sb);
           
            sb.insert(12, " How");
            System.out.println("string sb: " + sb);
            
            // Get length
            System.out.println("Length: " + sb.length());

            // Get SubString
           System.out.println("Sub: " + sb.substring(0, 5));
       }
}

StringBuilder class

The StringBuilder objects are like String objects except that they may be modified (mutable).The StringBuilder class is used when dealing with larger strings or modifying the contents of a string often.

The example above demonstrates modifying the String by using the append and insert methods and chaining by using the append method.

Output:

string sb: hello
string sb: hello world
string sb: hello world! are you?
string sb: hello world! How are you?
Length: 25
Sub: hello

A Simple Java Class: Employee

A Java class is often used to store or represent data for the construct that the class represents. For example, you could create a model (a programmatic representation) of an Employee. An Employee object defined by using this model contains values for empId, name, Social Security Number (ssn), and salary.

1 package com.example.domain;
2 public class Employee {
3      public int empId;
4      public String name;
5      public String ssn;
6      public double salary;
7
8      public Employee () {
9      }
10
11     public int getEmpId () {
12        return empId;
13    }
14 }

A constructor is used to create an instance of a class. Unlike methods, constructors do not declare a return type, and are declared with the same name as their class. Constructors can take arguments and you can declare more than one constructor.

Methods

When a class has data fields, a common practice is to provide methods for storing data (setter methods) and retrieving data (getter methods) from the fields.

1 package com.example.domain;
2 public class Employee {
3     public int empId;
4     // other fields...
5     public void setEmpId(int empId) {
6      this.empId = empId;
7   }
8     public int getEmpId() {
9       return empId;
10  }
11   // getter/setter methods for other fields...
12 }

Adding Instance Methods to the Employee Class

A common practice is to create a set of methods that manipulate field data: methods that set the value of each field, and methods that get the value of each field. These methods are called accessors (getters) and mutators (setters).

The convention is to use set and get plus the name of the field with the first letter of the field name capitalized (lower camel case). Most modern integrated development environments (IDEs) provide an easy way to automatically generate the accessor (getter) and mutator (setter) methods for you.

Notice that the set methods use the keyword this. The this keyword allows the compiler to distinguish between the field name of the class (this) and the parameter name being passed in as an argument. Without the keyword this, the net effect is that you are assigning a value to itself. (In fact, NetBeans provides a warning: “Assignment to self.”)

In this simple example, you could use the setName method to change the employee name and the setSalary method to change the employee salary.

Note: The methods declared on this slide are called instance methods. They are invoked by using an instance of this class.

Creating an Instance of a Class

To construct or create an instance (object) of the Employee class, use the new keyword.

/* In some other class, or a main method */Employee emp = new Employee();
emp.empId = 101;    // legal if the field is public,
                    // but not good OO practice
emp.setEmpId(101); // use a method instead
emp.setName("John Smith");
emp.setSsn("011-22-3467");
emp.setSalary(120345.27);

Creating an instance of the Employee Class

  • You need to allocate memory for the Employee object and call a constructor in the class to initialize all the instance variables of the class.
  • To allocate memory, new operator is used and to initialize all the instance variables of the class, the constructor is invoked.
  • An instance of an object is created when you use the new keyword with a constructor. All the fields declared in the class are provided with memory space and initialized to their default values.
  • If the memory allocation and constructor are successful, a reference to the object is returned as a result. In the example above, the reference is assigned to a variable called emp.
  • After all the data fields are set with values, you have an instance of an Employee with an empId with a value of 101, name with the string John Smith, Social Security Number string (ssn) set to 011-22-3467, and salary with the value of 120,345.27.

Constructors

A constructor is used to create an instance of a class. Constructors can take parameters. A constructor is declared with the same name as its class.

 
public class Employee {
       public Employee() {
       }
}
 Employee emp = new Employee();

Default and No-Arg Constructors

  • Every class must have at least one constructor.
  • If you do not provide any in a class’s declaration, the compiler creates a default constructor that takes no arguments when it’s invoked.
  • The default constructor initializes the instance variables to the initial values specified in their declarations or to their default values (zero for primitive numeric types, false for boolean values, and null for references).
  • If your class declares constructors, the compiler will not create a default constructor.
  • In this case, you must declare a no-arg constructor if default initialization is required.
  • Like a default constructor, a no-arg constructor is invoked with empty parentheses

package Statement

The package keyword is used in Java to group classes together. A package is implemented as a folder and, like a folder, provides a namespace to a class.

Packages

In Java, a package is a group of (class) types. There can be only one package declaration for a file. Packages create a namespace, a logical collection of things, like a directory hierarchy. Packages prevent name collision and also provide access control to classes. It is a good practice to always use a package declaration.

import Statements

You could refer to a class using its fully qualified namespace in your applications, as in the following example:

java.util.Date date = new java.util.Date();

But that would require a lot of typing. Instead, Java provides the import statement to allow you to declare that you want to reference a class in another package.

Notes: It is a good practice to use the specific, fully qualified package and class name to avoid confusion when there are two classes with the same name, as in the following example: java.sql.Date and java.util.Date. The first is a Date class used to store a Date type in a database, and java.util.Date is a general purpose Date class. As it turns out, java.sql.Date is a subclass of java.util.Date.

Modern IDEs, like NetBeans and Eclipse, automatically search for and add import statements for you. In NetBeans, for example, use the Ctrl + Shift + I key sequence to fix imports in your code.

Summary

The import keyword is used to identify classes you want to reference in your class. The import statement provides a convenient way to identify classes that you want to reference in your class.

import java.util.Date;

You can import a single class or an entire package:

import java.util.*;

You can include multiple import statements:

import java.util.Date;
import java.util.Calendar;

It is good practice to use the full package and class name rather than the wildcard * to avoid class name conflicts.

import Statements

import statements follow the package declaration and precede the class declaration. An import statement is not required. By default, your class always imports java.lang.*. You do not need to import classes that are in the same package:

package com.example.domain;
import com.example.domain.Manager; // unused import

Java Is Pass-By-Value

The Java language uses pass-by-value for all assignment operations. This means that the argument on the right side of the equal sign is evaluated, and the value of the argument is assigned to the left side of the equal sign.

To visualize this with primitives, consider the following:

int x = 3;
int y = x;

The value of x is copied and passed to y. If x is later modified (for example, x = 5;), the value of y remains unchanged. For Java primitives, this is straightforward. Java does not pass a reference to a primitive (such as an integer), but rather a copy of the value.

Pass-By-Value for Object References

For Java objects, the value of the right side of an assignment is a reference to memory that stores a Java object.

 Employee x = new Employee();
Employee y = x;

The reference is some address in memory.

When you assign the value of x to y, you are not creating a new Employee object, but rather a copy of the value of the reference.

Note: An object is a class instance or an array. The reference values (references) are pointers to these objects, and a special null reference, which refers to no object.

Objects Passed as Parameters

4 public class ObjectPassTest {
5     public static void main(String[] args) {
6           ObjectPassTest test = new ObjectPassTest();
7           Employee x = new Employee ();
8           x.setSalary(120_000.00);
9           test.foo(x);
10          System.out.println ("Employee salary: "
11          + x.getSalary());
12      }
13
14     public void foo(Employee e){
15     e.setSalary(130_000.00);
16     e = new Employee();
17     e.setSalary(140_000.00);
18 }

On line 6, a new Employee object is created and the reference to that object is assigned to the variable x. The salary field is set to 120_000 on line 8.

On line 9, the reference to x is passed to the foo method.

Line 15 of the foo method sets the salary value of e to 130_000. Because e refers to the same reference as x, the salary value for x is now 130_000.

Line 16 creates a new Employee object that changes the reference held in e. Now x is no longer referred to in the foo method.

Line 17 set the salary field, but x is unaffected as e no longer holds a reference to x.

The output from the program is:

Employee salary: 130000.0

Garbage Collection

When an object is instantiated by using the new keyword,memory is allocated for the object. The scope of an object reference depends on where the object is instantiated:

public void someMethod() {
    Employee e = new Employee();
    // operations on e
}

When someMethod completes, the memory referenced by e is no longer accessible. Java’s garbage collector recognizes when an instance is no longer accessible and eligible for collection.

Garbage is automatically collected by the JVM. The timing of the collection depends upon many factors.

Related Post