Book plug – OCA Java SE 7

February 19, 2014

The recent posts are based on my reading of the book (http://www.manning.com/gupta/). It is a good book, really easy read, and a nice grounding for the exam 1ZO-803.

After reading the book, you only need to do some practice exams and then you are ready.

http://itssmee.wordpress.com/2014/02/19/java-inheritance/

http://itssmee.wordpress.com/2014/02/17/java-basics-code-and-rules

http://itssmee.wordpress.com/2014/02/17/java-data-types-code-and-rules/

http://itssmee.wordpress.com/2013/12/16/java-methods-and-encapsulation/

http://itssmee.wordpress.com/2014/02/17/java-flow-control-code-and-rules/

http://itssmee.wordpress.com/2014/02/19/java-string-stringbuilder-arrays-and-arraylist-code-and-rules/

http://itssmee.wordpress.com/2014/02/19/java-exceptions-code-and-rules/

http://itssmee.wordpress.com/2014/02/19/java-inheritance/

I hope you enjoy them as a reference, they are not as good as the book – you should buy that :-)

Java inheritance

February 19, 2014

Inheritance

We will use the simple example most used:

class BaseEmployee {
    String name;
    String address;
    String phoneNumber;
    float yearsExperience;
}

class Manager extends BaseEmployee {
    int teamSize;
    void reportProjectStatus() {}
}

This and Super

this always points to its own instance of itself. Most common example is using this to differentiate instance from local variables:

class Example {

    String value1;             //Instance
    String value2;             //variables

    Example (String value1) {
        this.value1=value1;   //makes clear that the instance variable with the this.
    }


}

class Programmer extends BaseEmployee {
    String[] programmingLanguages;
    void writeCode() {}
}

Here we can see the two different types of employee, Manager and Programmer. Both of these inherit from the BaseEmployee class, and then each of them adds their own methods. These two classes are called subclasses, derived classes, extended classes or child classes, where as BaseEmployee can be referred to Base class, superclass or parent class.

Consider this, a method which accepts a class of BaseEmployee will also accept a subclass of BaseEmployee, meaning you could pass in Manager, for example.

Inheritance allows you to specialise a class by it extending (inheriting) other variables / methods from the parent. This means you are reusing code already defined, rather than re-inventing the wheel.

In the example above, the child class programmer has access to the variables from the parent so you can set the value of name in the child class even though it belongs to the parent class. Oh course there are the access limitations:

Inherited base members:

  • Default access, this means the base and derived class must belong to the same package
  • protected access, this means the derived class can access regardless of package which the base and derived class belong
  • public – well every class can access these
  • Not inherited base members:

  • private access, the derived class does not see these when defined in the base
  • A derived class does not inherit the base class’s constructor – it can call them though
  • Derived classes can also define their own constructor, static methods, variables etc as well as overriding or hiding the base class’s methods / variables etc.

    Abstract base class

    You cannot instantiate abstract classes
    An abstract class does not have to have abstract methods, however an abstract method in a class means it has to be an abstract class
    A derived class extending a abstract base class has to implement all the abstract methods of the base class

    Summarise the rules:

  • A base class / Superclass / Parent class is inherited (extended) by other classes
  • A derived class / subclass / Extended class / child class inherits / extends from a base class
  • Interface

    Interfaces are similar to abstract classes, an interface defines abstract methods (which are all public) and constants.

    Taking the example from before we can apply some interfaces. With the subclasses of Manager and Programmer we can define interfaces which force these classes to implement.

    
    interface Training {
        public void attendTraining();
    }
    
    interface Interview {
        public void conductInterview();
    }
    
    class BaseEmployee {
        String name;
        String address;
        String phoneNumber;
        float yearsExperience;
    }
    
    class Manager extends BaseEmployee implements Interview, Training {
        int teamSize;
        void reportProjectStatus() {}
        public void conductInterview() {                //Have to implement this
               System.out.println("I, manager, am conducting an interview");
        }
        public void attendTraining() {                //Have to implement this
               System.out.println("I, manager, am attending training");
        }
    }
    
    class Programmer extends BaseEmployee implements Training {
        String[] programmingLanguages;
        void writeCode() {}
        public void attendTraining() {                //Have to implement this
               System.out.println("I, programmer, am attending training");
        }
    }
    
    

    NB: the method signatures implemented in the class which is implementing an interface must match. Otherwise this a compile error.

    interface Training {
        public void attendTraining(String[] topics);    //By adding String[] topics, I need to change the implementation
    
    class Manager extends BaseEmployee implements Interview, Training {
        int teamSize;
        void reportProjectStatus() {}
        public void conductInterview() {                //Have to implement this
               System.out.println("I, manager, am conducting an interview");
        }
        public void attendTraining(String[] topics) {                //Have to implement this
               System.out.println("I, manager, am attending training");
        }
    }
    
    class Programmer extends BaseEmployee implements Training {
        String[] programmingLanguages;
        void writeCode() {}
        public void attendTraining(String[] topics) {                //Have to implement this
               System.out.println("I, programmer, am attending training");
        }
    }
    

    A class can only inherit from one class. The reason for this, each class could have the same method but a different meaning, so then which of these methods is inherited?

    
    class Example1 {
         public String greeting() {
             return new Sting("Why hello there");
         }
    }
    
    class Example2 {
         public String greeting() {
             return new Sting("How do");
         }
    }
    
    Class Employee extends Example1, Example2 {
          //Which greeting is called?
    }
    
    

    However, a class can implement many interfaces!

    
    interface ExampleInterface1 {
          String greeting();
    }
    
    interface ExampleInterface2 {
          String greeting();
    }
    
    class Employee implements ExampleInterface1, ExampleInterface2 {
         //Even though we are implementing two interfaces, both define the same method - this is fine as we just need to implement this method
    }
    

    Some rules:

  • A class implements a interface, an interface cannot inherit a class
  • An interface can extend / inherit another interface
  • Abstract class can extend a concrete class, and the other way
  • Abstract class can implement interfaces
  • Abstract class can extend another Abstract class
  • Reference and object types
    class Employee {
    	String name;
    	String address;
    	String phoneNumber;
    	float experience;
    }
    
     interface Training {
     	public void attendTraining();
     }
    
    class Programmer extends Employee implements Training {
    	String[] languages;
    	public void attendTraining() {
    		System.out.println("Programmer attending training");
    	}
    }
    
    class ExampleSpace {
    	public static void main(String[] args) {
    		Programmer p = new Programmer();
    		p.languages = new String[] {"Java", "JavaFX"};
    		
    		System.out.println(p.languages[0]);  //Java
    		
    		p.name = "Test";
    		
    		System.out.println(p.name);  //Test
    		
    		p.attendTraining();
    		
    		//All fine and Dandy, I have created a programmer object and I can access everything.
    		
    		Employee e1 = new Programmer(); //Wait what is this?
    		
    		//e1 is refering to an object of class Programmer, as this extends Employee.
    		
    		/*
    		However, this does not mean it can access everything that Programmer has, e.g.
    		
    			e1.languages = new String[] {"Java", "JavaFX"};
    		
    			System.out.println(e1.languages[0]);
    
    		This will not work as these are specific to the class Programmer. This code will not compile.
    		*/
    
    		//This is fine though, as these belong to the class Employee		
    		e1.name = "Test";
    		
    		System.out.println(e1.name);
    
    		/*
    		Employee does not implement an interface, so this will not work
    		
    			e1.attendTraining();
    		
    		*/
    		
    		//You can also refer to Programmer via the interface!
    		
    		Training t1 = new Programmer();
    		
    		/*
    		Guess what Training cannot do?
    		
    			t1.languages = new String[] {"Java", "JavaFX"};
    		
    			System.out.println(t1.languages[0]);
    			
    			t1.name = "Test";
    		
    			System.out.println(t1.name);
    		
    		It cannot see any of these as it's type is the interface Training. This would not compile.
    		*/
    		
    		//But it can do
    		
    		t1.attendTraining();
    		
    		//All well and good.
    		//Lets just take a look at these:
    		
    		//Programmer p2 = new Employee();  -- this will NOT compile. You cannot refer to a base class using a derived class.
    		//Programmer p3 = new Training(); -- this will NOT compile. You cannot create an object of the type interface.
    	}
    }
    

    You can create an Array of objects, based on a common class, in this case Training which is implemented by Programmer and Manager:

    
    Training[] t1 = new Training[] {
           new Programmer()
           , new Manager()
    };
    
    for (Training tt : t1) {
         tt.attendTraining();
    }
    
    //NB: The base class cannot be added as it does not implement Training, and Training cannot be added.
    
    Casting

    In the example above I place objects of types Programmer and Manager into an array of Training. I can use Casting to reference those objects.

    
    Manager m1 = new Manager();
    m1.teamSize = 5;
    Manager m2 = new Manager();
    m2.teamSize = 15;		
    Training[] t = new Training[] {
    	m1
    	, m2
    	, new Programmer()
    };
    		
    for (Training t1 : t) {
          if (t1 instanceof Manager) {
    	    Manager m = (Manager)t1;  //Casting t1 as a manager as it is of the type manager
    	    if (m.teamSize > 10) {
    		  System.out.println("Why are you on training?");
    		  continue;           //Move on to the next iteration of the loop
    	    }
          }
          t1.attendTraining();
    }
    
    

    This and Super

    this refers to the entity of itself. This is commonly used to distiguish instance variables from method. Example:

    class Example {
         String name;      //Instance
         String address;   //variables
    
         Example(String name) {  
             this.name = name;    //distinguish instance from method variable
         }
    
         Example(String name, String address) {
             this(name);                          //Calls the constructor which only takes name
             this.address = address;              //sets address
         }
    
    }
    

    Another example of using this to call the “default” constructor.

    class Example {
         String name;      //Instance
         String address;   //variables
         String postcode;
    
         Example() {                            	//Constructor which does not take any arguments
              name = "No data";
              address = "No data";
              postcode = "No date";
         }
    
    
         Example(String name, String address, String postcode) {
              this();				//This must be the first line of the method
              if (name != null) this.name = name;
              if (address != null) this.address = address;
              if (postcode != null) this.postcode = postcode;
              
         }
              
    }
    

    this can also be used to access inherited members of a base class in the derived class.

    Super

    This is normally used when a derived class define methods already present in the base class.

    class Employee {
    	String name;
    }
    
    class Programmer extends Employee {
    	String name;
    	
    	void setNames() {
    		this.name = "Programmer";
    		super.name = "Employee";
    	}
    	
    	void printNames() {
    		System.out.println(this.name);
    		SYstem.out.println(super.name);
    	}
    }
    

    You can also refer to constructors with super:

    class Employee {
    	String name;
    	Employee(String name) {
    		this.name = name;
    	}
    }
    
    class Programmer extends Employee {
    	String[] languages;
    	
    	Programmer(String name, String[] languages) {
    		super(name);                    //As with the this example, this call to the constructor must be the first line of code.
    		this.languages = languages;
    	}	
    }
    

    You can’t use this and super in static methods, the code will fail to compile!

    Polymorphism

    It means of many forms, think of a method e.g. talk, which depending on the object it belongs to you get a “different” result, but nevertheless the result is talking.

    abstract class Employee {
    	String name;
    	
    	public void reachOffice() {
    		System.out.println("Reached the office");
    	}
    	
    	public abstract void startProjectWork();  //Here we have defined a method which has to be implemented when employee is extended. Each object will deal with this in thier own way.
    }
    
    class Programmer extends Employee {
    	public void startProjectWork() { //This is also referred to as a overridden method
    		writeCode();
    		writeUnitTests();
    	}
    
    	private void writeCode() {
    		System.out.println("writing code");
    	}
    	
    	private void writeUnitTests() {
    		System.out.println("writing unit tests");
    	}
    }
    
    class Manager extends Employee {
    	public void startProjectWork() { //Have to implement this as I have extended Employee!
    		meetClients();
    		defineProject();
    		assignTeam();
    	}
    	
    	private void meetClients() {
    		System.out.println("Meeting with clients");
    	}
    	
    	private void defineProject() {
    		System.out.println("defining project");
    	}
    	
    	private void assignTeam() {
    		System.out.println("assigning team");
    	}
    }
    
    class PolyMorphism {
    	public static void main(String[] args) {
    		Employee e1 = new Programmer();   //creates object of Programmer and assigns to Employee
    		Employee e2 = new Manager();	//create object of Manager and assigns to Employee
    		
    		e1.reachOffice();  //This is defined in the Employee class
    		e2.reachOffice();
    		
    		e1.startProjectWork();  //Method from the programmer
    		e2.startProjectWork();  //Method from the manager
    	}
    }
    

    Note above, the reference variables of type Employee when the method startProjectWork is called they behave in accordance to the classes defined. startProjectWork is polymorphic in the same way talk is.

    The method in the abstract class means you have to implement it, in doing so you are actually overriding it. This method can be either abstract or not, and the access modifiers can be the same or less.

    NB: This is overridden methods – this is a method with the same name, number and type of arguments. Do not confuse with overloaded methods which accept a different number or type of parameters.

    The difference between variables bound at compile time and runtime:

    class Employee {
    	String name = "employee";
    
    	void printName() {
    		System.out.println(name);
    	}
    }
    
    class Programmer extends Employee {
    	String name = "programmer";
    
    	void printName() {
    		System.out.println(name);
    	}
    }
    
    class BindingExample {
    	public static void main(String[] args) {
    		Employee emp = new Employee();
    		Employee programmer = new Programmer();
    		
    		System.out.println(emp.name);         //prints employee
    		System.out.println(programmer.name);  //prints employee - Because the type of the variable is employee - this is bound at compile time
    		emp.printName();			//prints employee - accesses method within Employee
    		programmer.printName();			//prints programmer - access overridden method in Programmer
    	}
    }
    
    Interfaces

    Lets implement Polymorphism with interfaces, if we stay with the same objects as before (Employee, Programmer, and Manager) we shall implement finishWork().

    
    interface Project {
    	void finishWork();
    }
    
    class Programmer extends Employee implements Project {
    	public void finishWork() {
    		System.out.println("Coding complete");
    		System.out.println("unit tests complete");
    	}
    }
    
    class Manager extends Employee implements Project {
    	public void finishWork() {
    		System.out.println("QA complete");
    		System.out.println("Documentation done");
    	}
    }
    
    class PolyMorphWithInterfaces {
    	public static void main(String[] args) {
    		Project p1 = new Programmer();   //Because programmer and manager implement Project
    		Project p2 = new Manager();	//then the type of the variable can be Project
    		//If you stored these objects as type Employee you would not be able to call this method
    		
    		p1.finishWork() //returns "Coding complete" and "unit tests complete"
    		p2.finishWork() //returns "QA complete" and "Documentation done"
    	}
    }
    

    All fine and Dandy. A little disappointing that you have to define the type as Project, this limits us somewhat. We can address this by having Employee implement Project which, because Programmer and Manager extend Employee, means Employee types can call finishWork().

    interface Project {
    	void finishWork();
    }
    
    class Employee implements Project {
    	public void finishWork() {
    		System.out.println("Employee is done");
    	}
    }
    
    class Programmer extends Employee {
    	public void finishWork() {
    		System.out.println("Coding complete");
    		System.out.println("unit tests complete");
    	}
    }
    
    class Manager extends Employee {
    	public void finishWork() {
    		System.out.println("QA complete");
    		System.out.println("Documentation done");
    	}
    }
    
    class PolyMorphWithInterfaces {
    	public static void main(String[] args) {
    		Employee p1 = new Programmer();   
    		Employee p2 = new Manager();	
    		
    		p1.finishWork() //returns "Coding complete" and "unit tests complete"
    		p2.finishWork() //returns "QA complete" and "Documentation done"
    	}
    }
    

    Nice and clean…

    Remember, Polymorphism is overridden methods, not overloaded.

    reference: http://www.manning.com/gupta/

    Java exceptions code and rules

    February 19, 2014

    try – catch – finally

    
    try {
    
    //This is where you try your code
    
    }
    catch (Exception e) {
    
    //If an exception occurs, it is caught here
    //You can have multiple catch blocks for each different Exception, e.g. ArrayOutOfBoundsException, FileNotFoundException, etc.
    
    }
    finally {
    
    //This is where you tidy up, close files that sort of thing
    //This code ALWAYS executes, regardless if an exception is thrown
    //There is only ever one instance of the finally in a try-catch-finally block
    
    }
    
    

    There are Java Exception, stack overflow, array index out of bounds, etc, but you can also create your own. Exceptions are thrown, hence they are caught when you try the code. You can stack try-catch-finally, e.g. try some code, and then try code within that code.

    public class ExceptionExample {
    	public static void main(String[] args) {
    		int counter = 0;
    		int[] arr = new int[] {1,2,3,4};
    		
    		try {
    			System.out.println(arr[4]);
    			counter = 1;
    		}
    		catch (ArrayIndexOutOfBoundsException ae) {
    			System.out.println("An exception has been caught!");
    		}
    		finally {
    			counter = counter + 10;
    		}
    		
    		System.out.println(counter); //this prints 10 because the exception was thrown, otherwise it would print 11
    	}
    }
    

    If there is a return statement in the catch, the finally is still executed!

    The finally does not execute only when:

    Application termination (try or catch execute Sysem.exit())
    Fatal errors – the JVM crashes

    
    public class ExceptionExample {
    
    	int getInt() {
    		int res = 0;
    		int[] arr = new int[] {1,2,3,4};
    		
    		try {
    			System.out.println(arr[4]);
    			
    		}
    		catch (ArrayIndexOutOfBoundsException ae) {
    			res = 1;
    			System.out.println("An exception has been caught!");
    			return res;    //Because this is here, even though finally is executed the value returned will be 1 as this is the designated return value.
    		}
    		finally {
    			res = res + 100;
    		}
    		return res;
    	}
    	public static void main(String[] args) {
    		
    		ExceptionExample t = new ExceptionExample();
    		System.out.println(t.getInt());
    	}
    }
    
    

    The above applies to a primitive. For an object, the finally does affect the value returned because you are referencing the object. It can’t modify the primitive return type.

    
    	StringBuilder getValue() {
    		StringBuilder res = new StringBuilder("10");
    		int[] arr = new int[] {1,2,3,4};
    		
    		try {
    			System.out.println(arr[4]);
    		}
    		catch (ArrayIndexOutOfBoundsException ae) {
    			System.out.println("An exception has been caught!");
    			return res;    
    		}
    		finally {
    			res.append(100);
    		}
    		return res;
    	}
    	public static void main(String[] args) {
    		
    		ExceptionExample t = new ExceptionExample();
    		System.out.println(t.getInt());    //This returns 10100
    	}
    

    Some rules:

    A try block can be followed by a catch or finally block, or both. However, if the code in the try can throw a checked exception then this needs to be thrown by your method.
    A finally block cannot appear before a catch

    The order of the exceptions do matter when the classes are related. If you try to catch an exception of the base before the derived then the code will not compile. As an example, FileNotFound would come before IOException, as this reflects both the hierarchy and logic :-)

    You can catch and/or throw exceptions, so your code can try, then catch an exception and re-throw it. However if your code does re-throw it you must declare this.

    import java.io.*;
    
    public class ExceptionExample {
    	FileInputStream fis;
    	
    	public void load() throws FileNotFoundException {  //You need to declare this otherwise it fails to compile
    		try {
    			fis = new FileInputStream("file.txt");
    		}
    		catch (FileNotFoundException fnf) {
    			throw fnf;
    		}
    	}
    }
    

    Alternatively you can just throw, without having to check anything:

    public void load() throws IOException {
    	fis = new FileInputStream("file.txt");
    	fis.close();
    }
    
    Categories

    There are three categories:

  • Checked
  • Runtime
  • Errors
  • FileNotFound is a checked exception, it is thrown if the file cannot be found. A checked exception is a subclass of the java.lang.Exception class, but not a subclass of java.lang.RuntimeException.

    If a method uses a method which may throw a checked exception, it must

  • use try-catch block
  • and/or

  • throw the exception in the methods signature
  • Not doing this means the code will fail to compile.

    By declaring these exceptions, the user is aware of the exception that could occur and writes code to handle this.

    Runtime exceptions, also known as unchecked exceptions, an example is NullPointerExeption. These represent a programming error (e.g. you didn’t instantiate an object). It is a subclass of java.lang.RuntimeException.

    You can catch runtime exceptions. Saying that you can prevent runtime exceptions by using code as well.

    
    //This code will through a runtime exception
    
    int[] arr = new int[] {0,2,4,6,8};
    
    System.out.println(arr[5]);  //This is the runtimeexception!
    
    //This code uses a try-catch block
    
    try {
    	System.out.println(arr[5]);
    }
    catch (ArrayIndexOutOfBoundsException e) {
    	System.out.println("the array is not as big as you think...");
    }
    
    //However, you could just use logic....
    
    if (arr.length > 5) {
    	System.out.println(arr[5]);
    }
    

    Finally there are Errors. An example of which is StackOverflowError, this is thrown by the JVM when the size of the memory required is too large. It is a serious exception.
    Errors are a subclass of java.lang.Error.
    Errors are not part of a method signature.
    Errors can be caught by an exception handler, but should not be.

    Common exceptions
    ArrayIndexOutOfBoundException

    As previously covered, you are trying to reference an array entry outside of the limits (positive or negative).

    
    int[] arr = new int[] {0,2,3,5,6};
    
    System.out.println(arr[5]);
    System.out.println(arr[-1]);
    
    
    IndexOutOfBoundsException

    You are trying to reference an ArrayList entry outside of the limits (positive or negative).

    
    ArrayList<String> as = new ArrayList<String>();
    
    as.add("hello");
    as.add("world");
    
    System.out.println(as.get(100));
    System.out.println(as.get(-1));  //Both throw IndexOutOfBoundsException
    
    

    Simply, check the size of your Array / ArrayList before referencing entry.

    ClassCastException

    This is caused when you try and cast an object into something it is not part of:

    ArrayList<Employee> ees = new ArrayList<Employee>();
    ees.add(new Programmer());
    ees.add(new Manager());
    		
    Employee e1 = (Manager)ees.get(0);
    

    This can be easily resolved by validating the instanceof the object before casting:

    ArrayList<Employee> ees = new ArrayList<Employee>();
    ees.add(new Programmer());
    ees.add(new Manager());
    	
    if (ees.get(0) instanceof Manager) {
    	Employee e1 = (Manager)ees.get(0);
    }
    
    IllegalArgumentException

    This is thrown when the wrong value is passed into an argument. Think password, it must be 6 characters long:

    
    ...
    
    public void checkPassword(String password) throws IllegalArgumentException {
    	
    	if (password == null || password.length() < 6) {
    		throw new IllegalArgumentException("Password incorrect, please enter a password which is atleast 6 characters long");
    	}
    }
    
    ...
    
    public static void main(String[] args) {
    	try {
    		t.checkPassword(null);
    	}
    	catch (IllegalArgumentException ia)
    	{
    		System.out.println(ia.getMessage());   //This will print the message from the method
    	}
    }
    
    IllegalStateException

    From the Java API documentation, this “signals that a method has been invoked at an illegal or inappropriate time”.

    An example, a transfer:

    class Account {
    	private int accountNumber;
    	private double totalAmount;
    	private double transferAmount;
    	private boolean transfer;
    	
    	public void createTransfer(double amt) {
    		if (amt < totalAmount) {
                            totalAmount = totalAmount - amt;
    			transferAmount = amt;
    		}
    	}
    	
    	public void transfer() {
    		//code to send the money
    		transfer = true;
    	}
    	
    	public void modifyTransfer(float amt) {
    		if (!transfer) {
    			createTransfer(amt);
    		}
    		else {
    			throw new IllegalStateException("Money already being transferred");
    		}
    	}
    }
    
    public class ExceptionExample {
    	public static void main(String[] args) {
    		Account a = new Account();
    		try {
             		a.createTransfer(100.00);
    	        	a.transfer();
    		        a.modifyTransfer(150.00);
    		}
    		catch (IllegalStateException is) {
    			System.out.println(is.getMessage());
    		}
    	}
    }
    
    NullPointerException

    It occurs when:

  • reference variable that is explicitly assigned a null value
  • reference variable which has not been initialised
  • An unitialised local variable
  • Accessing nonexistent array positions
  • Using members of an array where the element is null
  • Some examples:

    class ExampleException {
    	static ArrayList<String> list = null;
    	public static void main(String[] args) {
    		list.add("Hello"); // this will throw a null pointer exception
    
    		//You can prevent null pointer by checking the object
    
    		if (list != null) {
    			list.add("hello");
    		}
    
    		//However, if list was defined here:
    		ArrayList<String> list2;
    		if (list2 != null) {           //This would fail to compile - as local variables are not assigned a value
    			list2.add("hello");
    		}
    

    Another:

    class ExampleException {
    	static String[] strArr;
    	public static void main(String[] args) {
    		System.out.println(artArr[1]);  //This will throw a NullPointerException
    		//strArr is assigned null as it is a static. It's elements are not initialised
    		
    		String[] secondArr = new String[4];
    		
    		System.out.println(secondArr[1].toString()); //This will throw a NullPointerException
    		//This is because you are calling the method toString() on the null string
    		System.out.println(secondArr[1]); //this is fine, it will print null
    	}
    }
    

    NumberFormatException

    This is thrown when an invalid string, for example, is converted to a “number”:

    
    System.out.println(Interger.parseInt("ABCD"));  //This will throw a NumberFormatException
    System.out.println(Interger.parseInt("24_68"));  //This will throw a NumberFormatException, the underscore in the string
    System.out.println(Interger.parseInt("+246")) //All fine.
    
    //If we take the first example, this can be parsed by passing in a parameter:
    
    System.out.println(Interger.parseInt("ABCD", 16));
    
    
    ExceptionInInitializerError

    Thrown when a static initializer in the code throws a runtimeexception:

    //An example
    static {
    	int number = Integer.parseInt("65v", 16);
    }
    

    This error can only be caused by runtimeexceptions.

    StackOverflowError

    This should be managed by the JVM, it is thrown when the program calls itself too many times.

    NoClassDefFoundError

    A really annoying error when your classpath is not set, or not inclusive. You do not handle this with code, you just suffer trying to set the classpath :-)

    OutOfMemoryError

    Thrown when you have exhausted the memory on the heap.

    reference: http://www.manning.com/gupta/

    Java String, StringBuilder, Arrays, and ArrayList code and rules

    February 19, 2014

    String class

    
    String s1 = new String("Hello");
    String s2 = new String("Hello");   //Using the new operator means these are separate objects
    
    System.out.println(s1 == s2);  // print false - because you are comparing the objects addresses
    
    String s3 = "Goodbye";
    String s4 = "Goodbye";
    
    System.out.println(s3 == s4); // prints true - s3 and s4 are referring the same object, as they have the same sequence of characters. s4 is pointing to the same object as s3 (s3 created the object)
    
    String m1 = "morning";
    System.out.println("morning" == m1);   // prints true, referring to the same object
    
    String m2 = new String("morning");
    System.out.println("morning" == m2);   // prints false, different objects
    
    

    String has overloaded constructors!

    
    String s1 = new String("hello");
    
    char[] c1 = new char[] {'H','e','l','l','o'};
    String s2 = new String(c1);
    
    StringBuilder sb1 = new StringBuilder("hello");
    String s3 = new String(sb1);
    
    StringBuffer sbf1 = new StringBuffer("hello");
    String s4 = new String(sbf1);
    
    //A literal value for a String is null
    
    String s5 = null;
    
    

    To recap String objects created versus references, let me show you where String objects are created

    
    String s1 = new String("a string");  //object created
    String s2 = "a string";              //object created
    System.out.println("a string");      //reference 
    System.out.println("different string");  //object created
    System.out.println("different string" == "A string") //references (different string) and create (A string)
    String different_string = new String("a string");  //object created
    
    //This creates a total of five objects
    
    

    Strings are immutable

    Once created they can never be modified. String uses a char[] array to store the value “hello”.

    
    String exampleValue = "hello";
    
    //This is stored as a char[] e.g.
    
    char[] exampleValue = new char[]{'h','e','l','l','o'};
    
    

    It uses a final variable to store the value. This variable is private, meaning all methods of String appear to modify the string but in fact return a new String.

    Methods of String
    String example = new String("Hello World");
    
    //charAt(int index)
    System.out.println(example.charAt(0));   //returns H
    System.out.println(example.charAt(2));   //returns l
    
    //indexOf(char or String)
    System.out.println(example.indexOf('W'));  //6
    System.out.println(example.indexOf("rl")); //8 - start of rl
    System.out.println(example.indexOf("z"));  //-1 - not there
    System.out.println(example.indexOf('l'));  //2 first occurrence of l
    
    //substring(int start position, [int length])
    
    System.out.println(example.substring(6)); //World
    System.out.println(example.substring(0,5)); //Hello
    //NB: substring does not include the character at the end of the string
    
    //trim()
    
    String trimExample = new String("  Hello World  ");
    System.out.println(":"+trimExample+":");          //returns - :  Hello World  :
    System.out.println(":"+trimExample.trim()+":");   //returns - :Hello World:
    
    //replace(char, char) or replace(String, String)
    
    System.out.println(example.replace('o','P');            //returns - HellP WPrld
    System.out.println(example.replace("Hello","GOODBYE");  //returns - GOODBYE World
    
    //length()
    
    System.out.println(example.length()); //returns - 11 (remember length-1 gives you the position
    
    //startsWith() and endsWith()
    //startsWith(String, [int position])
    
    System.out.println(example.startsWith("H");   //return true
    System.out.println(example.startsWith("o",4); //returns true
    
    System.out.println(example.endsWith("d"));     //returns true
    System.out.println(example.endsWith("worlD")); //returns false
    
    //Methods can be chained together, when this is the case they are evaluated left to right
    
    System.out.println(example.replace(' ','X').substring(0,5)); //returns Hello
    System.out.println(example.replace(' ','Y').substring(5));   //returns YWorld
    
    //Nasty one!!!
    
    System.out.println(example.substring(0,2).startsWith('H'));  //this will not compile!!!!
    
    System.out.println(example.substring(0,2).startsWith("H")); //this returns true!!!!
    
    
    String concatenation and Equality
    
    int intValue1 = 10;
    int intValue2 = 20;
    
    String strValue1 = "abcde";
    
    String strValue2 = intValue1 + intValue2 + strValue1;  //evaluation is from left to right, so adds then concatenates
    
    System.out.println(strValue2);  //returns 30abcde
    
    String strValue3 = strValue1 + intValue1 + intValue2;
    
    System.out.println(strValue3);   // returns abcde1020
    
    String strValue4 = strValue1 + (intValue1 + intValue2);
    
    System.out.println(strValue4);   // returns abcde30
    
    //then there is the += to concatenate
    
    String example2 = "Hello";
    
    example2 += " world";
    
    String example3 = null;
    example3 += "example3";
    System.out.println(example3); //returns nullexample3
    
    

    For equality, lets look at the equals method from the class String

    public boolean equals(Object anObject) {
        if (this == anObject) {     //if the objects are the same, then return ture
            return true;
        }
        
        if (anObject instanceof String) {               //Object is a string
            String anotherString = (String)anObject;
            int n = count;
            if (n == anotherString.count) {   //checks if the length of the string in the two objects are the same
                 char v1[] = value;
                 char v2[] = anotherString.value;
                 int i = offset;
                 int j = anotherString.offset;
                 while (n-- != 0) {              //Iterate through each string comparing char by char
                      if (v1[i++] != v2[j++])
                      return false;              //If one does not match the other then false
                 }
                 return true;                    //If both match then true
         }
         return false;
    }
    

    Quite interesting, lets look at some examples:

    String example1 = new String("Hello");
    String example2 = new String("Hello");
    
    System.out.println(example1.equals(example2));  // returns true
    
    System.out.println(example1 == example2);       // return false - they are two different objects
    System.out.println(example1 != example2);       // return true - they are two different objects
    
    
    String example3 = "Goodbye";
    String example4 = "Goodbye";
    
    System.out.println(example3.equals(example4));  // returns true
    
    System.out.println(example3 == example4);       // returns true - they are the same objects (reference!)
    
    //== compares reference objects
    //equals compares String values
    
    

    StringBuilder

    Creating StringBuilder:

    StringBuilder sb1 = new StringBuilder();

    StringBuilder sb2 = new StringBuilder(sb1); //Constructor takes StringBuilder object (default length is 16)

    StringBuilder sb3 = new StringBuilder(100); //Constructor takes length of String

    StringBuilder sb4 = new StringBuilder(“Hello World”); //Constructor takes String (length is String + 16)
    [/code]

    Methods of StringBuilder
    
    //APPEND() - accepts String, char array and Object
    StringBuilder sbExample = new StringBuilder();
    sbExample.append(true);
    sbExample.append(100);
    sbExample.append('b');
    sbExample.append(39.99);
    sbExample.append("Hello");
    
    System.out.println(sbExample);  //returns true100b39.99Hello
    
    char[] c = {'H','e','l','l','o',' ','W','o','r','l','d'};
    sbExample.append(c,5,6);         //takes char array, start pos, and length
    System.out.println(sbExample);  //returns true100b39.99Hello World
    
    //Remember my class Example? Well it is mentioned on another posting, a simple class
    
    sbExample.append(new Example());  //Appends this object to the stringbuilder object
    
    

    The stringbuilder append method will call the .toString() method on the object, if you have not overwritten this (as in this case) it use the default implementation.

    Example of the append code:

    public AbstractStringBuilder append(boolean b) {
    if (b) {
    int newCount = count + 4; //adds 4 (length of "true") to count - which is the number of characters held in the StringBuilder object
    if (newCount > value.length) expandCapacity(newCount); //If the array is not long enough then it expands it

    value[count++] = 't';
    value[count++] = 'r';
    value[count++] = 'u';
    value[count++] = 'e';
    }
    else {
    ...
    }
    return this;
    }
    [/code]

    Next up is Insert.

    StringBuilder example = new StringBuilder("bot");
    
    example.insert("a",2);    //inserts the a before the t which is at position 2
    
    System.out.println(example); //returns boat
    
    

    You can also insert strings, and substrings of strings

    StringBuilder example2 = new StringBuilder("Hello my friend");
    
    char[] value = new char[]{'G','o','o','d','b','y','e',' ','w','o','r','l','d'};
    
    example2.insert(5,value,7,6);
    
    System.out.println(example2); // returns Hello world my friend
    
    

    How about Deleting, persisting example2

    
    example2.delete(5,11);   //5 is the start position, 11 is the length (6) added onto the start position
    System.out.println(example2);
    
    

    There is NO TRIM() method with StringBuilder

    reverse()

    Lets use a palindrome to demonstrate reverse :-) I mean, it is the best way to see it no?

    StringBuilder palinDrome = "Man o nam";
    
    palinDrome.reverse();
    
    System.out.println(palinDrome); //return man o naM
    
    
    replace()

    Replaces a sequence of characters based on their position, with another String.

    
    StringBuilder example = new StringBuilder("Hello my good friend");
    
    example.replace(6,20,"World");   //where 6 is the start position, and 20 is the end position, and World is the text to replace that space
    
    System.out.println(example);  //returns Hello World
    
    
    subSequence()

    Returns a CharSequence, which can easily be cast as a String if you want of the String in the StringBuilder

    
    StringBuilder exampleSubSeq = new StringBuilder("0123456789");
    CharSequence subr = exampleSubSeq.subSequence(5,8);     //start position is 5 and end position is 8 (everything before the end position)
    System.out.println(subr);                               //returns 567
    System.out.println(exampleSubSeq);                      //returns 0123456789
    
    

    Arrays

    What is an Array?

    A collection of primitive types, and/or a collection of objects.

    
    int primitiveArray[] = new int[] {1,2,3,4};
    String objectArray[] = new String[] {"Hello", "World", "Goodbye", "all"};
    
    
    Declaring arrays
    
    int primitiveArray[];
    
    int[] primitiveArray;  //Both of these are the same
    
    int[] primitiveArray[]; //is the same as:
    int[][] primitiveArray; //which is the same as:
    int primitiveArray[][]; //These are multi-dimensional arrays
    
    //You cannot define the size of the array in declaration
    int primitiveArray[2];
    int[3] primitiveArray;
    int[4] primitiveArray[4];
    //None of the above will compile
    
    
    Array allocation

    This is when specify the size of the array, please remember the size cannot change!!

    int primitiveArray[];
    String multiDArray[][];
    
    primitiveArray = new int[100];
    multiDArray = new String[5][5];
    
    //The following are incorrect and will not compile
    primitiveArray = new int[];
    //or
    primitiveArray[200] = new int;
    
    //You can pass in variables for array allocation
    
    int i = 100, j = 20;
    String objectArray[] = new String[i*j]; //an array with 2000 elements
    
    String objectArray[] = new String[Math.min(i,j)]; //an array of 20 elements
    
    //Multi-dimensional arrays
    
    int[] multi[];
    multi = new int[100][];   //This is fine - in the first bracket
    
    multi = new int[][100];   //This is not fine, it will not compile
    
    
    Array Initialisation

    Arrays can be initialised directly or through a loop.

    
    String[] stringArray = new String[4];
    
    for (int i = 0; i < stringArray.length; i++) {
        stringArray[i] = "Hello " + i;
    }
    
    //alternatively, you can set each value - in this instance the Hello string are overwritten
    
    stringArray[0] = "goodbye";
    stringArray[1] = "fairwell";
    stringArray[2] = "see ya";
    stringArray[3] = "ciao";
    
    // the following will compile but generate a runtime exception
    
    stringArray[4] = "oh dear";
    
    // code will fail to compile if you don't pass in a char, byte, short or int
    
    // You can combine all three, declaration, allocation, and initialisation e.g.
    
    String[] strArray = {"a","b","c"}; //declares an array of size 3 with the values. NB no need for new operator
    //You can use new, but you can't specify the size as well
    String[] strArray = new String[]{"a","b","c"}; //fine
    String[] strArray = new String[3]{"a","b","c"}; //fails to compile
    
    //the following does not compile
    String[] strArray;
    strArray = {"a","b"};
    
    //You need a new
    String[] strArray;
    strArray = new String[]{"a","b"};
    
    

    Asymmetrical multidimensional arrays, are multidimensional arrays which are not symmetrical - no surprise really. What does this mean?

    String multiAsymArr[][] = new String[][] {
                  {"1","2"},
                  null,
                  {"a","b","c"},
                  {"Z","Y",null,"x"},
           };
    
    //note the above does not have the same number of columns
    
    Interface, abstract, and object class arrays

    You can define an array type as an interface, abstract class, or a object class.

    
    interface exampleInterface { }
    class ExampleClass1 implements exampleInterface {}
    class ExampleClass2 implements exampleInterface {}
    
    ...
    
    exampleInterface[] exampleArray = new exampleInterface[] {
                                                  new ExampleClass1(),
                                                  new ExampleClass2(),
                                                  null
                                           };
    
    //This array can hold objects which implement the interface or nulls
    
    

    For Abstract class it is the same as interface, create the abstractclass. Create an array of the type the same as the abstract class and then it can hold objects which extend the abstract class or nulls.

    Finally Objects. Well every object extends Object, so an array of Object can hold any Object:

    interface exampleInterface { }
    class ExampleClass1 implements exampleInterface { }
    abstract class exampleAbstract{ }
    class ExampleClass3 extends exampleAbstract{ }
    
    ...
    
    Object[] objectArrayExample = new Object[] {
                                 new ExampleClass1(),
                                 new ExampleClass3(),
                                 new java.util.Date(),
                                 new String("hello world"),
                                 null,
                                 new Integer[10]
                         };
    
    //As you can see an Object array can hold all different types of objects - including null.
    

    To determine the number of elements in an array, use the method length. String has the method length() which returns the length of the string value.

    ArrayList

    Easier to use than an array. It automatically increases/decreases it's size (unlike an Array). You don't have to specify the initial size of the ArrayList. Some further pointers

  • null values can be added
  • interface List implemented
  • operators add, modify, and delete implemented
  • holds duplicate values
  • maintains order of values inserted
  • To iterate over an ArrayList you can use Iterator or ListIterator
  • Supports generics
  • declaring
    //you need to import ArrayList!!!!
    import java.util.ArrayList;
    
    public class ExampleCreateArrayList {
          public static void main(String[] args) {
                 ArrayList<String> example = new ArrayList<String>();
                 //As of Java version 7 you can create an arraylist like so:
                 ArrayList<String> example = new ArrayList<>();  //note the removal of String? Only Java 7 and higher
          }
    }
    //The initial size of an ArrayList is 10
    
    Adding elements

    We will stick with example now that it has been created as a ArrayList of String:

    //already done this
    //ArrayList<String> example = new ArrayList<String>();
    
    example.add("Hello");
    example.add("world");
    example.add("how");
    example.add("are");
    example.add("you");
    //all fine and dandy.
    //however we can add a value at a specified position.....
    example.add(3,"this is position three");
    
    //Accessing elements in an array is done via the enhanced for loop
    
    for (String element : example) {
         System.out.println(element);
    }
    
    /*This will output
    Hello
    world
    how
    this is position three
    are 
    you
    */
    
    //You can also use a ListIterator to access the elements
    ListIterator<String> exampleIterator = example.listIterator();
    
    while(exampleIterator.hasNext()) {
        System.out.println(exampleIterator.next());
    }
    
    

    NB: An Iterator or ListIterator, allows you to remove elements as you iterate over - this is not possible using a enhanced for loop.

    Modifying values
    import java.util.ArrayList;
    public class ModifyArrayListExample {
        public static void main(String[] args) {
            //So what we are going to do is create an arraylist, and then modify each value
            //rather than String, we will use StringBuilder as Strings are immutable
    
            ArrayList<StringBuilder> examArrList = new ArrayList<StringBuilder>();
            examArrList.add(new StringBuilder("First"));
            examArrList.add(new StringBuilder("Second"));
            examArrList.add(new StringBuilder("Third"));
    
            for (StringBuilder element : examArrList) {
                  element.append(" "+element.length());
            }
    
    
            //Now lets have a look at what we have done
    
            for (StringBuilder element : examArrList) {
                  System.out.println(element);
            }
    
            /*
                 First 5
                 Second 6
                 Third 5           
            */
    
            //Another nice little one.... You can replace/change a value:
            examArrList.set(2,new StringBuilder("This is position two!"));
    
            for (StringBuilder element : examArrList) {
                  System.out.println(element);
            }
    
            /*
                 First 5
                 Second 6
                 This is position two!
            */
    
        }
    }
    
    Removing elements

    There are two ways to remove elements:

  • remove(int index)
  • remove(Object o) -- Only the first occurrence of the object
  • Lets continue with the example above.

    
            //In the first instance lets remove an entry....
            examArrList.remove(2);
            for (StringBuilder element : examArrList) {
                  System.out.println(element);
            }
    
            StringBuilder exampleSB1 = new StringBuilder("example StringBuilder object");
    
            examArrList.add(exampleSB1);
            for (StringBuilder element : examArrList) {
                  System.out.println(element);
            }
            
            examArrList.remove(exampleSB1);
    
            for (StringBuilder element : examArrList) {
                  System.out.println(element);
            }
    
            //The new string is no longer in the list
    
    

    More methods to look at are

  • addAll(Collection c) - appends the collection to the end of the list
  • addAll(int index, Collection c) - appends all of the elements from the collection from position index to the end of the list
  • You can clear down your arraylist with the method .clear()

    
    ArrayList<String> example = new ArrayList<String>();
    example.add("Hello");
    example.add("world");
    example.add("goodbye");
    example.add("my friend");
    
    String val1 = example.get(1);
    System.out.println(val1); // return world
    
    int arrSize = example.size();
    System.out.println(arrSize); //return the size of the arraylist 4
    
    

    Other methods which are quite interesting... contains, indexof and lastIndexOf.

    //Create a Example Car class
    class Car {
        String model;
        Car(String model) {
            this.model = model;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (obj instanceof Car) {
                Car t = (Car)obj;
                boolean res = t.model.equals(this.model);
                return res;
            }
            else return false;
       }
    }
    
    public class Example {
        public static void main(String[] args) {
           ArrayList<Car> myArrayList = new ArrayList<Car>();
    
           Car c1 = new Car("316");
           Car c2 = new Car("Micra");
    
           myArrayList.add(c1);
           myArrayList.add(c2);
           myArrayList.add(c2);
    
           System.out.println(myArrayList.contains(new Car("316")); //returns true - this is because we have overridden equals
           System.out.println(myArrayList.contains(c1); //returns true
    
           System.out.println(myArrayList.indexOf(new Car("Micra"));  //return 1 - this is because we have overridden equals
           System.out.println(myArrayList.indexOf(c2));  //returns 1
    
           System.out.println(MyArrayList.lastIndexOf(new Car("Micra"));  //returns 2 - this is because we have overridden equals
           System.out.println(MyArrayList.lastIndexOf(c2)); //returns 2
      }
    }
    

    You can clone an ArrayList, as well as return a Array of an ArrayList. Below is an example showing both the toArray in action and noting how referencing an object can come into play.

    import java.util.ArrayList;
    
    class ExampleArray {
    
    	static ArrayList als; // = new ArrayList();
    	static ArrayList alsb; // = new ArrayList();		
    	static String[] sarr;
    	static StringBuilder[] sbarr;
    
    	public static void displayAL() {
    		System.out.println("Displaying Array Lists");
    		
    		for (String val: als)
    			System.out.println(val);
    			
    		for (StringBuilder val: alsb)
    			System.out.println(val);	
    	}
    	
    	public static void displayA() {
    		System.out.println("Displaying Arrays");
    		
    		for (int i = 0; i &lt; sarr.length; i++) {
    			System.out.println(sarr[i]);
    		}
    
    		for (int i = 0; i &lt; sbarr.length; i++) {
    			System.out.println(sbarr[i]);
    		}	
    	}
    
    	public static void main(String[] args) {
    		
    		
    		String s1 = new String(&quot;hello&quot;);
    		String s2 = new String(&quot;there&quot;);
    		
    		StringBuilder sb1 = new StringBuilder(&quot;good&quot;);
    		StringBuilder sb2 = new StringBuilder(&quot;day&quot;);
    		
    		als = new ArrayList();
    		alsb = new ArrayList();
    		
    		als.add(s1);
    		als.add(s2);
    		
    		alsb.add(sb1);
    		alsb.add(sb2);
    		
    		System.out.println("first run through");
    		displayAL();
    		
    		sarr = new String[als.size()];	
    
    		sarr = als.toArray(sarr);
    
    		sbarr = new StringBuilder[alsb.size()];
    
    		sbarr = alsb.toArray(sbarr);
    		
    		System.out.println("second run through");
    		displayAL();
    		displayA();
    		
    		System.out.print("Changed s1 from "+s1);
    		
    		
    		s1 = "zzzzz";
    		
    		
    		System.out.println(" to "+s1);
    		System.out.println("s1 is in Array List and String Array");
    		System.out.print("changed sb1 from "+sb1);
    		
    		
    		sb1.append(" my dear old ");
    		
    		
    		System.out.println(" to "+sb1);
    		System.out.println("sb1 is in Array List and String Array - what will we see?");
    		
    		System.out.println("third run through");
    		displayAL();
    		displayA();
    	}
    }
    

    The output from this is:

    first run through
    Displaying Array Lists
    hello
    there
    good
    day
    second run through
    Displaying Array Lists
    hello
    there
    good
    day
    Displaying Arrays
    hello
    there
    good
    day
    Changed s1 from hello to zzzzz
    s1 is in Array List and String Array
    changed sb1 from good to good my dear old
    sb1 is in Array List and String Array - what will we see?
    third run through
    Displaying Array Lists
    hello
    there
    good my dear old
    day
    Displaying Arrays
    hello
    there
    good my dear old
    day

    NB: how the change to the StringBuilder variable is reflected in both the ArrayList and the Array, this is because both the ArrayList and Array are holding references to the object.

    Equals, how objects are compared

    Let's take an example of expanding the functionality of the equals methodology.

    import java.util.Date;
    import java.text.DateFormat;
    import java.util.Locale;
    import java.util.ArrayList;
    
    class ExampleEquals {
    	private String name;
    	private Date dob;
    	
    	ExampleEquals(String n, Date b) {
    		name = n;
    		dob = b;
    	}
    	
    	public String getName() {
    		return name;
    	}
    	
    	public Date getDOB() {
    		return dob;
    	}
    	
    	public boolean equals(Object o) {	   //NB: The equals method accepts a Object, not a ExampleEquals.
    		if (o instanceof ExampleEquals) {  //NB: You then evaluate the object to see if it is of the instance you want
    			ExampleEquals t = (ExampleEquals)o;  //NB: Then you can instantiate it
    			return (name.equals(t.getName()) && dob.equals(t.getDOB()));
    		}
    		
    		return false;
    	}
    }
    
    class TestExampleEquals {
    	public static void main(String args[]) throws Exception {
    
    		DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.UK);
    		
    		ExampleEquals e1 = new ExampleEquals("test", df.parse("25/12/1950"));
    		
    		ExampleEquals e2 = new ExampleEquals("tess", df.parse("25/12/1950"));
    		
    		ExampleEquals e3 = new ExampleEquals("test", df.parse("25/12/1950"));
    		
    		System.out.println("e1 compared to e2 == "+e1.equals(e2));
    		System.out.println("e2 compared to e3 == "+e2.equals(e3));
    		System.out.println("e3 compared to e1 == "+e3.equals(e1));
    		
    		//As you can see, comparing these objects uses our definition of the equals method
    		
    		//Lets us throw an ArrayList into the mix
    		
    		ArrayList<ExampleEquals> al = new ArrayList<ExampleEquals>();
    		al.add(e1);
    		al.add(e2);
    		al.add(e3);
    		
    		ExampleEquals e4 = new ExampleEquals("tess", df.parse("25/12/1950"));
    		
    		System.out.println("ArrayList contains e2 == "+al.contains(e2));
    		
    		System.out.println("ArrayList contains e4 == "+al.contains(e4));
    		
    	}
    }
    

    Output from this is:

    e1 compared to e2 == false
    e2 compared to e3 == false
    e3 compared to e1 == true
    ArrayList contains e2 == true
    ArrayList contains e4 == true

    Always be sure the equals takes an Object and not the actual class.

    The equals contract:

  • It is reflexive - any non-null reference value x, x.equals(x) should return true;
  • It is symmetric - any non-null reference value x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive - any non-null reference value x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent - any non-null reference value x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals() comparisons on the objects is modified.
  • for any non-null reference value x, x.equals(null) should return false.
  • The following violates the contract:

    public boolean equals(Object o) {
          return false;
    }
    

    A method which returns true (for equals) when passed a null violates this contract. The equals method cannot touch the values it is comparing, just compare them.

    reference: http://www.manning.com/gupta/

    Java Flow Control code and rules

    February 17, 2014

    Let’s start with

    If then else

    all pretty straight forward:

    int intValue = 100;
    String result = "";
    
    if (intValue == 100)
        result = "A";
    else if (intValue == 50)
        result = "B";
    else if (intValue == 20)
        result = "C";
    else result = "F";
    
    

    Some little things with if then else:

    
    //If must contain code
    
    boolean booleanValue = false;
    int intValue = 0;
    String stringValue = "Hello";
    
    //This won't compile because there is no if body
    if (booleanValue)
    else
       System.out.println("false value");
    
    if ((intValue=intValue+10) >= 10);  //This is invalid as we have no body
    
    //This is fine
    if (stringValue.equals("Hello"))
        intValue = 100;
    
    if (stringValue.equals("Hello"))
        intValue = 100;
        stringValue = "Hello World";    //This line is not part of the if statement
    
    if (stringValue.equals("Hello"))
        intValue = 100;
        stringValue = "Hello World";    //This line is not part of the if statement
    else stringValue = "goodbye";      //This block of code will not compile as we are missing the curlies
    
    if (stringValue.equals("Hello"))
        intValue = 100;
    else 
        intValue = 200;
        System.out.println("the stringValue is not equal to Hello");
    //The above will compile, but the last statement will always execute - not what we want.
    //The curlies resolves this for us:
    
    if (stringValue.equals("Hello")) {
        intValue = 100;
        stringValue = "Hello World";    //This line is NOW part of the if statement
    } else {
        stringValue = "goodbye";      
    }
    
    if (stringValue.equals("Hello")) {
        intValue = 100;
    } else { 
        intValue = 200;
        System.out.println("the stringValue is not equal to Hello");
    }
    
    However, this is an interesting example:
    
    if (stringValue.equals("Hello"))   //Lets assume it does
        for (int i = 0; i < 10; i++)
            System.out.println(i);      //because this belongs to the for loop, it is part of the if body
    
    //Output from the above:
    0
    1
    2
    3
    ... 
    10
    
    //Comparisons..
    
    //Always remember, comparing strings should be done with .equals() not ==
    
    if (booleanValue = true)
        System.out.println("the booleanValue is true");
    else
        System.out.println("the booleanValue is false");
    
    //This will output booleanValue is true because the assignment was successful
    
    

    Switch

    Simple example:

    
    int intValue = 200;
    
    switch (intValue) {
        case 100: System.out.println("it is 100!");
           break;
        case 200: System.out.println("it is 200!");
           break;
        case 300: System.out.println("it is 300!");
           break;
        default: System.out.println("it is not 100, 200, or 300!");
           break;
    }
    
    

    Comparing Switch to if then else

    String month = "Jan";
    
    //If statment
    
    if (month.equals("Dec") || month.equals("Jan") || month.equals("Feb") )
        System.out.println("Winter");
    else if (month.equals("Mar") || month.equals("Apr") || month.equals("May"))
        System.out.println("Spring");
    else if (month.equals("Jun") || month.equals("Jul") || month.equals("Aug"))
        System.out.println("Summer");
    else if (month.equals("Sep") || month.equals("Oct") || month.equals("Nov"))
        System.out.println("Autumn");
    else 
        System.out.println("n/a");
    
    //Case statement
    
    switch(month) {
        case "Dec":
        case "Jan":
        case "Feb": System.out.println("Winter");
           break;
        case "Mar":
        case "Apr":
        case "May": System.out.println("Spring");
           break;
        case "Jun":
        case "Jul":
        case "Aug": System.out.println("Summer");
           break;
        case "Sep":
        case "Oct":
        case "Nov": System.out.println("Autumn");
           break;
        default: System.out.println("n/a");
    

    Switch can only be used with some data types, byte, short, int, char and String.

    
    int intValue = 100;
    switch (intValue*10) {
        //...                         This is fine as you are comparing a int value.
    }
    
    double doubleValue = 100.00
    switch (doubleValue) {
       //...                          Cannot be used in a switch - if will fail to compile
    }
    
    //More stuff
    
    int iv2 = 10, iv3 = 30;
    
    switch (intValue) {
       case iv2+iv3: System.out.println(intValue);  //fails as these are not constants
          break;
       case 10*30: System.out.println(intValue);    //all fine!!!
          break;
       case 10.0: System.out.println("ooh it is a double????");  //no can do, remember
          break;
    }
    
    //finals
    
    final int iv2 = 10, final int iv3 = 20, final int iv4;
    
    iv4 = 100;
    
    switch (intValue) {
       case iv2: System.out.println(iv2);           //this is fine
          break;
       case iv2+iv4: System.out.println(intValue);  //fails as iv4 is not considered constant as it was only declared.
          break;
       case 10*30: System.out.println(intValue);    //all fine!!!
          break;
    }
    
    String strValue = "XX";
    
    switch(strValue) {
        case "XY": System.out.println("XY");
            break;
        case null: System.out.println("a null");    //Nulls are not allowed!!!
    }
    

    For loop

    Simple example of a for loop:

    int counter = 10;
    for (int i = 0; i < counter; i++)
    {
         System.out.println(i);
    }
    

    Output being:
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9

    You can break the for statement into initialisation, condition, and update. There can be many of each in a for loop:

    
    int counter = 10;
    
    for (int i = 100, j = 0;          //Initialisation of multiple variables
            j <= i && counter <100;   //Multiple conditions
            i--, j++, counter += 10)  //Multiple updates
    {
          System.out.println(i+","+j+","+counter);
    }
    
    

    With the output being:

    100,0,10
    99,1,20
    98,2,30
    97,3,40
    96,4,50
    95,5,60
    94,6,70
    93,7,80
    92,8,90

    You can also call methods from the update section.

    Nested loops, these allow you to traverse multi-dimensional arrays.

    
    int multiArray[][] = new int[5][4];
    
    //So if we wanted to initialise this with the value -1, we could traverse it with a nested loop.
    
    for (int i = 0; i < multiArray.length; i++)
    {
         for (int j = 0; j < multiArray[i].length; j++)
         {
              multiArray[i][j] = -1;
         }
    }
    
    

    The Enhanced for loop

    We have already seen this with ArrayLists. A simple example:

    
    ArrayList<String> exampleAL = new ArrayList<String>();
    
    exampleAL.add("value 1");
    exampleAL.add("value 2");
    
    //Using a for loop would look like this
    
    for (Iterator<String> i = exampleAL.iterator(); i.hasNext();)
          System.out.println(i.next());
    
    // And as a enhanced for loop
    
    for (String value : exampleAL)
          System.out.println(value);
    
    //Nested ArrayList and enhanced for loops
    //We still have exampleAL
    
    ArrayList<String> exampleAL2 = new ArrayList<String>();
    
    exampleAL2.add("1 value");
    exampleAL2.add("2 value");
    
    ArrayList<ArrayList<String>> exampleNestedAL = new ArrayList<ArrayList<String>>();
    
    exampleNestedAL.add(exampleAL);
    exampleNestedAL.add(exampleAL2);
    
    for (ArrayList<String> al : exampleNestedAL)
          for (String value : al)
              System.out.println(value);
    
    //Within a enhanced for loop you can modify reference object but not primitives.
    
    StringBuilder sbArr[] = {
          new StringBuilder("Value 1"),
          new StringBuilder("Value 2")
    };
    
    for (StringBuilder value : sbArr)
         System.out.println(value);   //Will print Value1 and Value2
    
    for (StringBuilder value : sbArr)
         value.append(" appended");
    
    for (StringBuilder value : sbArr)
         System.out.println(value);   //Will print "Value1 appended" and "Value2 appended"
    
    //However, you cannot add, e.g.
    
    for (StringBuilder value : sbArr)
         value = new StringBuilder("new value");
    
    for (StringBuilder value : sbArr)
         System.out.println(value);   //Will print "Value1 appended" and "Value2 appended"
    
    //Another example of the nest loop
    
    for (String v1 : exampleAL)
        for (String v2 : example AL2)
              System.out.println(v1+" : "+v2);
    
    /* output being:
    Value 1 : 1 Value
    Value 1 : 2 Value
    Value 2 : 1 Value
    Value 2 : 2 Value
    */
    
    

    You cannot use enhanced for loop to:

  • Initialise arrays
  • delete or remove elements from a collection
  • Allows for the creation of only one loop variable
  • Don’t use it to initialise, modify, or filter arrays
  • While and do loops

    A simple while loop example

    final int ten = 10;
    boolean finish = false;
    int counter = 0;
    while (!finish) {
        if (counter < ten)
        {
            System.out.println(counter+1);
            counter++;
        }
        else finish = true;
    }
    
    //Remember to define your boolean correctly, if it were true it would not enter the first iteration
    
    

    do while loop

    The do while loop always completes the first iteration before evaluating the condition. If we take the example above:

    int counter = 0;
    boolean finished = false;
    do
    {
         if (counter < 10)
         {
              System.out.println(counter);
              counter++;
         }
         else finished = true;
    } while (!finished)
    
    

    In this instance if counter >= 10 or finished were true, the loop would output the value of counter. A nice example of this is:

    
    int counter=100;
    do
    {
       counter++;                   //increments the counter by 1, line below also increments the counter to evaluate the condition
    } while (++counter > 200)       //this evaluates to false so does not continue with the loop
    System.out.println(counter);   //prints 202
    
    counter=100
    while(++counter > 200)        //evaluates to false, but incremented the counter in the process
    {
        counter++;
    }
    System.out.println(counter);  //print 201
    

    You should try and use the while loops when you don’t know the iterations, where as the for loop should be used when you do know.

    In loops you can break and continue. Break breaks out of the current loop, however in a nested loop it only breaks out of the loop it belongs to. For example, if the break is on the inner loop it will break out of that but the outer loop will continue.

    The continue will continue process in the current loop, but will skip any process on that iteration where the continue is issued.

    Labels….

    Simple examples of break and continue referencing a label:

    String[] values = {"value 1","value 2"};
    exampleLabel:
    for (String v : values)
    {
         if (v.equals("value 1"))
            break exampleLabel;              //This exits the loop to the end of the exampleLabel block
         System.out.println(v);
    }
    
    //Another example
    exampleLabel:
    for (String v : values)
    {
         for (String v1 : values)
         {
            if (v1.equals("value 1"))
               break exampleLabel;           //This exits the loop to the end of the exampleLabel block, so exits both loops
            System.out.println(v1);
         }
    }
    
    exampleLabel2:
    for (String v : values)
    {
         for (String v1 : values)
         {
            if (v1.equals("value 1"))
               continue exampleLabel2;           //This resumes the loop from the label exampleLabel block
            System.out.println(v1);              //Outputs value 1 value 1
         }
    }
    
    //The following will not compile
    exampleLabel:
    int t = 100;
    
    //However this will
    exampleLabel: {
        int t = 100;
    }
    

    Rules of labels are:

  • you can label a code block using {}
  • you can label all loops
  • you can label if’s and switch’s
  • you can label expressions
  • you can label assignments
  • you can label return statements
  • you can label try blocks
  • you can label throws
  • reference: http://www.manning.com/gupta/


    Follow

    Get every new post delivered to your Inbox.