Java Lesson - Objects

Introduction
Java is an programming language which is type safe and object oriented. The benefit of working in Java is that you can easily write good code but the downsides it's even easier to write bad code if you're not careful. Hopefully after looking this page over you can see the advantages and disadvantages of various design patterns. I didn't' go into too much detail why to favor one design over another, but feel free experiment with them and do any additional research.

Creating Classes
Creating a class object is pretty straight forward in Java but there are plenty consider when designing them. Here is the syntax structure of a simple class object. The following code contains a single constructor that doesn't take any parameters along with a single method called doSomething.

JavaObject.java public class JavaObject { public JavaObject{} public void doSomething{ System.out.println("Something"); } }

Now to test this object we could construct a program with a main function to see if how JavaObject operates. The object, JavaObject, is assigned the symbol obj in this example. When the symbol executes the method doSomething the coded output is printed to standard out.

Unit Test public static void main(String[] args) { JavaObject obj = new JavaObject; obj.doSomething; } Standard Out Something

As you can probably imagine this JavaObject isn't too useful. Besides the limited functionality of the object, the class doesn't promote code re-useability.

Creating Interfaces
Interfaces are a class object that only contains method declarations used by other classes. One way to think about an interface is like a facade. The interface designs how an object should look like and be used, without having any of the code. Let's rewrite the JavaObject as an interface.

As you can see the keyword class was replaced with interface and only how the method doSomething is defined.

JavaObject.java public interface JavaObject { public void doSomething; }

Lets make two simple objects that use this interface to demonstrate how to incorporate this design. After the defined of the java program you add the keyword implements to specify the interface the class will be using. Also the annotation @Override is used to ensure that the method within the scope of the object will be called.

Hello.java public class Hello implements JavaObject{ @Override public void doSomething { System.out.print("Hello"); } }

World.java public class World implements JavaObject{ @Override public void doSomething { System.out.print(" World.\n"); } }

Now lets see what happens when this unit test executes. This test assigns a symbol to the class and immediately executes the objects symbol. As you can see, the strings from Hello and World are printed out on the same line.

Unit Test public static void main(String[] args) { Hello annyeong = new Hello; annyeong.doSomething; World segye = new World; segye.doSomething; } Standard Out Hello World.

Creating Abstract Classes
Within Java you can design a class object similar to the interface design that contain executable code, they are called abstract classes. Similar how you can define the name of a function and it's parameters in an interface, you can define abstract functions. Generally it's better to use an interface over an abstract classes. Abstract class can difficulty for other programmers and there are limitations on how you can implement abstract objects.

The majority of time, when I write an abstract class it's for my own personal unit test. To demonstrate this, I quickly made a mock unit test script designed to compare List data types when it comes to quickly insert values into a list. In this test I compared ArrayList, LinkedList, Stack and Vectors.

FactorialTest.java
To be honest, I wrote this class hastily and only in a few minutes but that should consider a strength of abstract classes. The downside of this however I used integers to calculate the factorials. The sequence gets "fuzzy" after !12. There are two functions that are worth knowing about timeIt and findAVG. The function timeIt run a single test and returns how long it took in nano seconds. The function findAVG runs a given number of trails on timeIt and returns the average amount of time the function took. I decided to write the function findNext an abstract method to demonstrate how you can create them but it would be better to have that code defined within FactorialTest.java I also included a method called print that will print out the stored factorial sequence for a sanity check.

import java.util.LinkedList; import java.util.List; public abstract class FactorialTest { protected List list; public FactorialTest(List list){ this.list = list; } 	//Finds the next factorial of a sequence. abstract protected void findNext; public void print{ for( int i = 0; i < list.size; i++ ) System.out.println(i + "! = " + list.get(i) ); }    // Times how long it takes to build a sequence of factorial numbers. public long timeIt(int range){ list.clear; long start = System.nanoTime; for(int i = 0; i < range; i++) findNext; long end = System.nanoTime - start; return end; }    public long findAVG(int trials, int range){ List results = new LinkedList; // Building time result data for(int i = 0; i < trials; i ++) results.add( timeIt(range) ); // Averaging results data long avg = 0; for(long time : results) avg += time; avg /= trials; return(avg); } }

The following class objects are extended from FactorialTest.java. If you refactor findNext into UnitTest.java, these objects would only consists of a single constructor.

Factorial_ArrayList.java
import java.util.ArrayList; public class Factorial_ArrayList extends FactorialTest{ public Factorial_ArrayList { super( new ArrayList); } 	@Override protected void findNext { if( list.size == 0 ) list.add(0,1); else list.add( 				list.size, 				list.get( list.size - 1 ) * list.size  			); } }

Factorial_LinkedList.java
import java.util.LinkedList; public class Factorial_LinkedList extends FactorialTest{ public Factorial_LinkedList{ super(new LinkedList ); } 	@Override protected void findNext { if( list.size == 0 ) list.add(0,1); else list.add( 				list.size, 				list.get( list.size - 1 ) * list.size  			); } }

Factorial_Stack.java
import java.util.Stack; public class Factorial_Stack extends FactorialTest{ public Factorial_Stack{ super(new Stack ); } 	@Override protected void findNext { if( list.size == 0 ) list.add(0,1); else list.add( 				list.size, 				list.get( list.size - 1 ) * list.size  			); } }

Factorial_Vector.java
import java.util.Vector; public class Factorial_Vector extends FactorialTest{ public Factorial_Vector{ super(new Vector ); } 	@Override protected void findNext { if( list.size == 0 ) list.add(0,1); else list.add( 				list.size, 				list.get( list.size - 1 ) * list.size  			); } }

UnitTest.java
Over a hundred trials, Stack and Vector general were the fastest with LinkedList coming in a close third. That's not saying Stacks and Vectors should be favored over LinkedLists. LinkedLists was the most consistent data type. The performance of both the Stack and Vector fluctuated at times, either running extremely quickly or slowly.

Also remember that I reused the list object in timeIt. If we did a single trial the results would be much different. One the first pass of the timeIt, the list would be internally copied over into a new list to accommodate the growing list. Instead of creating a new instance of list, I just cleared all the stored values which probably means the list still has the memory locations allocated for the factorial numbers. On a single trial, ArrayList took 3,762,489 nano seconds while the other three data types took around 50,000 nano seconds to compile. public class UnitTest { public static void test(int trials, int sequenceRange, UnitTest test){ System.out.println("On average, " + test.getClass.getName + 	" took " + test.findAVG(trials, sequenceRange) + " nano seconds."); }    public static void main(String[] args) { // test(num of trials, sequence range, object) test(100, 13, new Factorial_ArrayList ); test(100, 13, new Factorial_LinkedList ); test(100, 13, new Factorial_Stack ); test(100, 13, new Factorial_Vector ); } }

Standard Output On average, Factorial_ArrayList took 31978 nano seconds. On average, Factorial_LinkedList took 24628 nano seconds. On average, Factorial_Stack took 21801 nano seconds. On average, Factorial_Vector took 20625 nano seconds.

Anonymous Classes
Java wasn't designed to support closure but they do have first class citizens with the anonymous class. As of Java 1.7 anonymous classes are the only way to attempt functional(?) programming in Java. There is an possibility that a lambda function will appear in Java 1.8, but the proposed syntaxs are pretty ugly. Speaking of ugly let's see what a Y-combinator looks like in Java. Note, I stole this version for reasons that are about to be apparent. I honestly didn't want to try tackling this one in Java and got I lucky by finding this at Rosetta Code. This y combinator can calculate factorials and fibonacii numbers. If you want to try inputting different values just change the fib.call or fac.call methods within the System.out.println statement at the very bottom.

YCombinator.java
interface Function { public B call(A x); } interface RecursiveFunc extends Function, F> { } public class YCombinator { public static  Function fix(final Function, Function> f) { RecursiveFunc> r = new RecursiveFunc<Function<A,B>> { public Function<A,B> call(final RecursiveFunc<Function<A,B>> w) { return f.call(new Function<A,B> {            public B call(A x) {                 return w.call(w).call(x);             }             }); }    };     return r.call(r); }    public static void main(String[] args) { Function<Function<Integer,Integer>, Function<Integer,Integer>> almost_fib = new Function<Function<Integer,Integer>, Function<Integer,Integer>> { public Function<Integer,Integer> call(final Function<Integer,Integer> f) { return new Function<Integer,Integer> { public Integer call(Integer n) { if (n <= 2) return 1; return f.call(n - 1) + f.call(n - 2); }        };         }     };     Function<Function<Integer,Integer>, Function<Integer,Integer>> almost_fac = new Function<Function<Integer,Integer>, Function<Integer,Integer>> { public Function<Integer,Integer> call(final Function<Integer,Integer> f) { return new Function<Integer,Integer> { public Integer call(Integer n) { if (n <= 1) return 1; return n * f.call(n - 1); }        };         }     };     Function<Integer,Integer> fib = fix(almost_fib); Function<Integer,Integer> fac = fix(almost_fac); System.out.println("fib(10) = " + fib.call(10)); System.out.println("fac(10) = " + fac.call(10)); } }

Standard Output fib(10) = 55 fac(10) = 3628800

Telescoping
Telescoping is consider a bad design for a class. A telescoped class contains multiply constructs used to initialize the object. In the following example uses multiple constructs to define the symbol var. The main issue with this design is you can't ensure how and what values will be used to set the value for the var symbol Object. Also this pattern doesn't scale well. Lets say that JavaObject has more than a single symbol, how about ten symbols. Well, we already have six different constructors, so with some basic arithmetic, the programmer would have to code sixty symbols for the given class.

JavaObject.java public class JavaObject { Object var; public JavaObject{ var = null; }    public JavaObject(Integer aInt){ var = aInt; }    public JavaObject(String aStr){ var = aStr; }    public JavaObject(Character aChr){ var = aChr; }    public JavaObject(Boolean aBool){ var = aBool; }    public JavaObject(Float aFlt){ var = aFlt; } }

JavaBeans
JavaBeans is a standard design pattern that solves the problems of telescoping classes and a common standard that you'll run into if you do any Java programming. Every Java beans contains a default constructor that doesn't take in any parameters and methods are used to set or get a class symbol. The downsides of this pattern is that every bean will be mutability and inconsistencies may occur in the bean's stored values. The methods setType, setName, and setAInt must be used with valid data before the bean could be properly used.

JavaObject.java public class JavaObject { private String type = "NOT SET"; private String name = "NOT SET"; private int aInt = -1; public String getType { return type; }    public void setType(String type) { this.type = type; }    public String getName { return name; }    public void setName(String name) { this.name = name; }    public int getAInt { return aInt; }    public void setAInt(int int1) { aInt = int1; }    public JavaObject{} }

Builders
The builder pattern attempts to solve the problem of the bean. Class objects following the builder pattern can support immutable objects and optional parameters. The following code sample creates an object called Person. As you can notice this Person object makes use of inner class called builder to initialize itself. With a little knowledge about generics you can take the builder pattern even father.

Person.java public class Person { private final String firstName; private final String lastName; private final int age; private Person(Builder builder){ firstName = builder.firstName; lastName = builder.lastName; age = builder.age; }    public static class Builder{ // Required at instantiation. private final String firstName; private final String lastName; // Optional passed in paramaters private int age = -1; public Builder(String firstName, String lastName){ this.firstName = firstName; this.lastName = lastName; }        public Builder age(int age){ this.age = age; return this; }        public Person build{ return new Person(this); }       } }

Unit Test public static void main(String[] args) { Person bitDiddler = new Person.Builder("Bit", "Diddler").age(25).build; Person lispHacker = new Person.Builder("Alyssa","Hacker").build; }

Singleton
The singleton design pattern is a class object that can only be instantiated once. There are several ways you could try implemented a singleton object but my favorite design makes use of the enumeration class.

JavaObject.java public enum JavaObject { INSTANCE; public void doSomething{ System.out.println("Hello World!"); } }

Unit Test public static void main(String[] args) { JavaObject.INSTANCE.doSomething; } Standard Output Hello World!

Factory Objects
Factory objects are objects that can't be instantiated. An example you're probably already familiar with is the Math library. If not, here is a simple example that uses library to print out a calculated value for pi.

Unit Test public static void main(String[] args) { System.out.println(Math.PI); } Standard Out 3.141592653589793

The next code snippet I wrote is a factory function that finds the area from a set of points. I used the Point class within the awt library to act as a point on a xy plane. I wanted to only write one function to handle any number of points and not to use any trigonometry since I generally hate using it.

Area.java import java.util.List; import java.awt.Point; public class Area { private Area{}; public static double get(List<Point> pts){ int sum = 0; //Empty sets, single points and line segments will have an area of 0 if(pts.size < 3) return 0; for(int i = 0; i < pts.size; i++) if(i < (pts.size - 1) ) sum += Math.abs( 		   ( pts.get(i).x * pts.get(i+1).y ) - 		    ( pts.get(i+1).x * pts.get(i).y ) 		); else sum += Math.abs( 		   ( pts.get(i).x * pts.get(0).y ) - 		    ( pts.get(0).x * pts.get(i).y ) 		); sum /= 2; return(sum); } }

Unit Test public static void main(String[] args) { Point pt1 = new Point(0,0); Point pt2 = new Point(5,0); Point pt3 = new Point(0,5); Point pt4 = new Point(5,5); List<Point> list = new ArrayList<Point>; list.add(pt1); list.add(pt2); list.add(pt3); System.out.println("The area of this triangle is: " + Area.get(list)); list.add(pt4); System.out.println("The area of this quadrilateral is: " + Area.get(list)); } Standard Output The area of this triangle is: 12.0 The area of this quadrilateral is: 25.0

Tagged Classes
Tagged classes are a poor design to use and should be replaced with a pattern such as class hierarchies, which you will see in the next design pattern. This version of velocity uses an enumeration class to check the type of vehicle being used to calculate the velocity. As you can see, mph and knot are unused symbols that may not be initialized or used. The function get has a bloated switch statement to handle the enumeration object. I also wrote this extra sloppy if you couldn't tell. This object is an all around bad design, but an good anti-pattern though.

Velocity.java public class Velocity { enum Vehicles { CAR, BOAT }; Vehicles Vehicles ; // Tagged field for CAR double mph; // Tagged field for BOAT double knot; // Lazy way to do this, but you should get the point public Distance(boolean isCar){ if(isCar) vehicle = Vehicles.CAR; else vehicle = Vehicles.BOAT; }    public double get(double miles, double hours){ switch(vehicle ){ case BOAT: knot = (miles / hours) * 1.151 ; return(knot); case CAR: mph = miles / hours; return(mph); default: return(0); }    } }

Unit Test public static void main(String[] args) { Distance car = new Distance(true); Distance boat = new Distance(false); System.out.println("MPH rate the car is traveling: " + car.get(1, 1)); System.out.println("Knot rate the boat is traveling: " + boat.get(1,1)); } Standard Output MPH rate the car is traveling: 1.0 Knot rate the boat is traveling: 1.151

Class Hierarchies
To rewrite the tagged version of Velocity.java, I used an abstract class. This version is less likely to cause an errors at run time and is easier to read.

Velocity.java abstract class Velocity{ protected double miles; protected double hours; abstract double get; } class Boat extends Velocity{ public Boat(double miles, double hours){ super.miles = miles; super.hours = hours; }    double get{ return (miles/hours) * 1.151 ;} } class Car extends Velocity{ public Car(double miles, double hours){ super.miles = miles; super.hours = hours; }    double get { return (miles/hours) ;} }

Unit Test public static void main(String[] args) { Car car = new Car(1,1); Boat boat = new Boat(1,1); System.out.println("MPH rate the car is traveling: " + car.get); System.out.println("Knot rate the boat is traveling: " + boat.get); } Standard Output MPH rate the car is traveling: 1.0 Knot rate the boat is traveling: 1.151

Inheritance and Composition
If possible, try to implement composition over inheritance. You already seen inheritance at work in abstract classes but as a quick refresher, here is a quick and dirty snippet of an sub class.

public class Company{ public String toString{ System.out.println("Someone didn't override this."); } } public class Apple extends Company{ @Override public String toStrint{ System.out.println("Who names their company after a fruit?"); } }

For an more interesting demonstration, the next snippet shows how to bring a Pythonic dictionary into Java. To accomplish this, we are going to need two classes, one forwarding class and one wrapper class. In my example, the Dict class will act as the forwarding class and PyDict will become the wrapper class.

Since Python's dictionary is a mapping data structure, Java's Map data structure came in handy. The Dict class role is to just forward all methods contained in the Map class.

Dict.java import java.util.Collection; import java.util.Map; import java.util.Set; public class Dict<K,V> implements Map<K,V>{ private final Map<K,V> map; public Dict(Map<K,V> map) { this.map = map; } public void clear { map.clear; } public boolean containsKey(Object key) { return map.containsKey(key); } public boolean containsValue(Object value) { return map.containsValue(value); } public Set<java.util.Map.Entry<K, V>> entrySet { return map.entrySet; } public V get(Object key) { return map.get(key); } public boolean isEmpty { return map.isEmpty; } public Set<K> keySet { return map.keySet; } public V put(K key, V value) { return map.put(key, value); } public void putAll(Map<? extends K, ? extends V> map) { this.map.putAll(map); } public V remove(Object key) { return map.remove(key); } public int size { return map.size; } public Collection<V> values { return map.values; } }

Next I made another class called PyDict, to extend the Dict class. PyDict is a wrapper object around Dict that adds extra methods that can be called. In this case, I implemented Python's dictionary update and keys methods.

PyDict.java public class PyDict<K,V> extends Dict<K,V>{ public PyDict(Map<K, V> map) { super(map); } public Set<K> keys{ return super.keySet; }    public void update(K key, V value){ if( super.containsKey(key) ) super.put(key, value); else System.err.println("Unable to update dictionary"); } }

Unit Test public static void main(String[] args) { Map<Integer, String> map = new HashMap<Integer, String>; map.put(1, "World"); PyDict<Integer, String> dict = new PyDict<Integer, String>(map); dict.put(0, "Hello "); for(String value : dict.values ) System.out.print(value); System.out.println; dict.update(1, "World!"); for(String value : dict.values ) System.out.print(value); } Standard Output Hello World Hello World!