Effective Java, even c# (1) Creating and Destroying Objects

So GREAT The new version of Effective Java(2nd edition)  is! (Better than Effective c# 1 million times)

I’m reading this book and finding that lots of the skill can be used by other language programmers, especially c#’s.

This series of notes will cover the the things for both java and c#.

Wish you like it.

Creating and Destroying Objects

  • Item 1: Consider static factory methods instead of constructors

Just a static method to create the instance. It can replace the constructor. You can then make the constructor invisible(private or protected) or not.

class A{
    // constructors and others things.
    public static A newInstance(){
        return new A();
    }
}

This skill can be used by both Java and c#.

The advantages you can control more than the constructor. You can create a new instance or an old one(like the Singleton pattern). Or you can return other implement for the return type. This will make it more like the abstract factory pattern.

One more advantage I think, is that you can check the parameters. I remembered that it is not good to throw exception at the constructor in the CLR via c# by Jeffrey Richter. With this static method, you can throw anything freely.

  • Item 2: Consider a builder when faced with many constructor
    parameters

The builder is for the constructor with a lot of parameters. We used to provide some overload constructors for some default parameters. It’s named “telescope” by Bloch (the writer of this book).

Here is the example:

// Telescoping constructor pattern - does not scale well!
public class NutritionFacts {
	private final int servingSize; // (mL) required
	private final int servings; // (per container) required
	private final int calories; // optional
	private final int fat; // (g) optional
	private final int sodium; // (mg) optional
	private final int carbohydrate; // (g) optional

	public NutritionFacts(int servingSize, int servings) {
		this(servingSize, servings, 0);
	}

	public NutritionFacts(int servingSize, int servings, int calories) {
		this(servingSize, servings, calories, 0);
	}

	public NutritionFacts(int servingSize, int servings, int calories, int fat) {
		this(servingSize, servings, calories, fat, 0);
	}

	public NutritionFacts(int servingSize, int servings, int calories, int fat,
			int sodium) {
		this(servingSize, servings, calories, fat, sodium, 0);
	}

	public NutritionFacts(int servingSize, int servings, int calories, int fat,
			int sodium, int carbohydrate) {
		this.servingSize = servingSize;
		this.servings = servings;
		this.calories = calories;
		this.fat = fat;
		this.sodium = sodium;
		this.carbohydrate = carbohydrate;
	}
}

The builder can do the same things, and it looks more cool!

NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 0, 35, 27);

NutritionFacts cocaCola2 = new NutritionFacts.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).build();

The implement is so easy, and it makes the code more readable. (like the named parameters in python)

// Builder Pattern
public class NutritionFacts {
	private final int servingSize;
	private final int servings;
	private final int calories;
	private final int fat;
	private final int sodium;
	private final int carbohydrate;

	public static class Builder {
		// Required parameters
		private final int servingSize;
		private final int servings;
		// Optional parameters - initialized to default values
		private int calories = 0;
		private int fat = 0;
		private int carbohydrate = 0;
		private int sodium = 0;

		public Builder(int servingSize, int servings) {
			this.servingSize = servingSize;
			this.servings = servings;
		}

		public Builder calories(int val) {
			calories = val;
			return this;
		}

		public Builder fat(int val) {
			fat = val;
			return this;
		}

		public Builder carbohydrate(int val) {
			carbohydrate = val;
			return this;
		}

		public Builder sodium(int val) {
			sodium = val;
			return this;
		}

		public NutritionFacts build() {
			return new NutritionFacts(this);
		}
	}

	private NutritionFacts(Builder builder) {
		servingSize = builder.servingSize;
		servings = builder.servings;
		calories = builder.calories;
		fat = builder.fat;
		sodium = builder.sodium;
		carbohydrate = builder.carbohydrate;
	}
}

One more advantage for Java is you can make a Generic Builder and make sure you can use the parameterless method (like defualt constructor) to get the instance but not invoke the Class.newInstance.

// A builder for objects of type T
public interface Builder<T> {
    public T build();
}

Tree<T> buildTree(Builder<T> nodeBuilder){
    // use the nodeBuilder.build() to get a new node.
    ...
}

This is not a problem for c# because the “new()” constraint.

class Tree<T> where T : new()
{
    Tree<T> BuildTree()
    {
        // simply new T() for a new node.
        ...
    }
}

But you can also use this skill if you need to construct a new instance with some parameters.

  • Item 3: Enforce the singleton property with a private
    constructor or an enum type

Make the constructor private and set a static field or getter, it is what we said “singleton pattern”. Someone (GoF theirselfs?) said it is the worst in practice of all classic 23 design patterns.

Bloch noticed us invoking private constructor by reflection or serialization will make more than one instance here.

In the Java word, you need to make choice of  the static field and the static getter method. In the c# world, I think, you should always use the static property. it looks like the field and can do things which getter can do.

But now Java programmer can make it more elegant.

// Enum singleton - the preferred approach
public enum Elvis {
    INSTANCE;
    public void leaveTheBuilding() { ... }
}

Well…

Java wins!

  • Item 4: Enforce noninstantiability with a private constructor

Ok, it’s time for c# to beat back!

The noninstantiability class is the utility class (like Math). They just have a lot of static methods.

Java programmers need to make the default constructor private to defend someone who want to create a instance of it or inherit of it.

As a c# programmer, you just need to mark the class static!

  • Item 5: Avoid creating unnecessary objects

Make some local variable as a static field to escape create it every time.

It just a kind of refactor, no more to say.

Bloch also notice us the autobox unbox problem in the new Java.

// Hideously slow program! Can you spot the object creation?
public static void main(String[] args) {
	Long sum = 0L;
	for (long i = 0; i < Integer.MAX_VALUE; i++) {
		sum += i;
	}
	System.out.println(sum);
}
&#91;/sourcecode&#93;

Well, when you rewrite it via c#...

c# wins again!
<ul>
	<li><strong>Item 6: Eliminate obsolete object references</strong></li>
</ul>
This "obsolete" is not the ObsoleteAttribute in c#. It means some object you won't use it never.

Look the pop method below:


// Can you spot the "memory leak"?
public class Stack {
	private Object[] elements;
	private int size = 0;
	private static final int DEFAULT_INITIAL_CAPACITY = 16;

	public Stack() {
		elements = new Object[DEFAULT_INITIAL_CAPACITY];
	}

	public void push(Object e) {
		ensureCapacity();
		elements[size++] = e;
	}

	public Object pop() {
		if (size == 0)
			throw new EmptyStackException();
		return elements[--size];
	}

	/**
	 * Ensure space for at least one more element, roughly doubling the capacity
	 * each time the array needs to grow.
	 */
	private void ensureCapacity() {
		if (elements.length == size)
			elements = Arrays.copyOf(elements, 2 * size + 1);
	}
}

The new version pop is here:

public Object pop() {
	if (size == 0)
		throw new EmptyStackException();
	Object result = elements[--size];
	elements[size] = null; // Eliminate obsolete reference
	return result;
}

The pool, cache and the listeners and other callbacks (the registered even handler in c#) are mostly having this kind of memory leaks.

One word: whenever a class manages its own memory, the programmer should be alert for memory leaks.

  • Item 7: Avoid finalizers

Both Java and c# programmers should escape the using of finalizer.

Jeffrey Richter have said the same problem in the CLR via c#.

How to free the unmanaged resource?

If you are a c# programmer, you should use the disposable pattern and enjoy the “using” syntax.

As a Java programmer, you need implement your close() method and invoke it in the finally block.

If you must do something in the finalizer, don’t for get to call the super.finalize().

  • iron9light‘s item: Consider to use Dependency Injection

When you wanna create the object, you should consider to make the class interface-orianted and use Dependency Injection.

You can use the one of the exist frameworks, like Guice (by Google) for Java or Unity (by Microsoft) for c# both are open source, or you do it by yourself.

I’ve written some lightweight framework for my own project🙂

Tags: , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: