Wednesday, October 17, 2007

Custom String Values for Enum

The default string value for java enum is its face value, or the element name. However, you can customize the string value by overriding toString() method. For example,
public enum MyType {
ONE {
public String toString() {
return "this is one";
}
},

TWO {
public String toString() {
return "this is two";
}
}
}
Running the following test code will produce this:

public class EnumTest {
public static void main(String[] args) {
System.out.println(MyType.ONE);
System.out.println(MyType.TWO);
}
}
-------------
this is one
this is two

Another interesting fact is, once you override toString() method, you in effect turn each element into an anonymous inner class. So after compiling the above enum class, you will see a long list of class files:
MyType.class
MyType$1.class
MyType$2.class

Java Enum and Its Superclass

All java enum implicitly extend from java.lang.Enum. Since java doesn't allow multiple inheritance, enum types can't have superclass. They can't even extend from java.lang.Enum, nor java.lang.Object. It also means enum A can't inherit or extend enum B.

For example, the following is an invalid enum declaration:


public enum MyNumENUM extends Object {
ONE, TWO
}

Compiler error:
MyNumENUM.java:3: '{' expectedpublic enum MyNumENUM extends Object { MyNumENUM.java:6: expected
2 errors

The correct form should be:

public enum MyNumENUM {
ONE, TWO
}




Shallow Copy and Deep Copy

The java.lang.Object root superclass defines a clone() method that will, assuming the subclass implements the java.lang.Cloneable interface, return a copy of the object. While Java classes are free to override this method to do more complex kinds of cloning, the default behavior of clone() is to return a shallow copy of the object. This means that the values of all of the origical object’s fields are copied to the fields of the new object.

A property of shallow copies is that fields that refer to other objects will point to the same objects in both the original and the clone. For fields that contain primitive or immutable values (int, String, float, etc…), there is little chance of this causing problems. For mutable objects, however, cloning can lead to unexpected results. Figure 1 shows an example.


--------------------------------------------------------------------------------
import java.util.Vector;
public class Example1 {
public static void main(String[] args) {
// Make a Vector
Vector original = new Vector();
// Make a StringBuffer and add it to the Vector
StringBuffer text = new StringBuffer(”The quick brown fox”);
original.addElement(text);
// Clone the vector and print out the contents
Vector clone = (Vector) original.clone();
System.out.println(”A. After cloning”);
printVectorContents(original, “original”);
printVectorContents(clone, “clone”);
System.out.println(“——————————————————–”);
System.out.println();
// Add another object (an Integer) to the clone and
// print out the contents
clone.addElement(new Integer(5));
System.out.println(”B. After adding an Integer to the clone”);
printVectorContents(original, “original”);
printVectorContents(clone, “clone”);
System.out.println(“——————————————————–”);
System.out.println();
// Change the StringBuffer contents
text.append(” jumps over the lazy dog.”);
System.out.println(”C. After modifying one of original’s elements”);
printVectorContents(original, “original”);
printVectorContents(clone, “clone”);
System.out.println(“——————————————————–”);
System.out.println();
}

public static void printVectorContents(Vector v, String name) {
System.out.println(” Contents of \”" + name + “\”:”);
// For each element in the vector, print out the index, the
// class of the element, and the element itself
 for (int i = 0; i < v.size(); i++) {
  Object element = v.elementAt(i);
  System.out.println(” ” + i + ”(” +element.getClass().getName()+ “):” +element);
 }
System.out.println();
}
}
--------------------------------------------------------------------------------


Figure 1. Modifying Vector contents after cloning
In this example we create a Vector and add a StringBuffer to it. Note that StringBuffer (unlike, for example, String is mutable — it’s contents can be changed after creation. Figure 2 shows the output of the example in Figure 1.


--------------------------------------------------------------------------------


> java Example1
A. After cloning

Contents of “original”:

0 (java.lang.StringBuffer): The quick brown fox
Contents of “clone”:

0 (java.lang.StringBuffer): The quick brown fox
——————————————————–


B. After adding an Integer to the clone

Contents of “original”:

0 (java.lang.StringBuffer): The quick brown fox
Contents of “clone”:

0 (java.lang.StringBuffer): The quick brown fox

1 (java.lang.Integer): 5
——————————————————–


C. After modifying one of original’s elements

Contents of “original”:

0 (java.lang.StringBuffer): The quick brown fox jumps over the lazy dog.
Contents of “clone”:

0 (java.lang.StringBuffer): The quick brown fox jumps over the lazy dog.

1 (java.lang.Integer): 5
——————————————————–

--------------------------------------------------------------------------------


Figure 2. Output from the example code in Figure 1
In the first block of output (”A”), we see that the clone operation was successful: The original vector and the clone have the same size (1), content types, and values. The second block of output (”B”) shows that the original vector and its clone are distinct objects. If we add another element to the clone, it only appears in the clone, and not in the original. The third block of output (”C”) is, however, a little trickier. Modifying the StringBuffer that was added to the original vector has changed the value of the first element of both the original vector and its clone. The explanation for this lies in the fact that clone made a shallow copy of the vector, so both vectors now point to the exact same StringBuffer instance.

This is, of course, sometimes exactly the behavior that you need. In other cases, however, it can lead to frustrating and inexplicable errors, as the state of an object seems to change “behind your back”.

The solution to this problem is to make a deep copy of the object. A deep copy makes a distinct copy of each of the object’s fields, recursing through the entire graph of other objects referenced by the object being copied. The Java API provides no deep-copy equivalent to Object.clone(). One solution is to simply implement your own custom method (e.g., deepCopy()) that returns a deep copy of an instance of one of your classes. This may be the best solution if you need a complex mixture of deep and shallow copies for different fields, but has a few significant drawbacks:





A common solution to the deep copy problem is to use Java Object Serialization (JOS). The idea is simple: Write the object to an array using JOS’s ObjectOutputStream and then use ObjectInputStream to reconsistute a copy of the object. The result will be a completely distinct object, with completely distinct referenced objects. JOS takes care of all of the details: superclass fields, following object graphs, and handling repeated references to the same object within the graph. Figure 3 shows a first draft of a utility class that uses JOS for making deep copies.


--------------------------------------------------------------------------------


import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;


public class MyDeepCopy {
/**
* Returns a copy of the object, or null if the object cannot
* be serialized.
*/

public static Object copy(Object orig) {
Object obj = null;
try {
// Write the object out to a byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(orig);
out.flush();
out.close();
// Make an input stream from the byte array and read
// a copy of the object back in.
ObjectInputStream in = new ObjectInputStream(
new ByteArrayInputStream(bos.toByteArray()));
obj = in.readObject();
}
catch(IOException e) {
e.printStackTrace();
}
catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
return obj;
}
}




Figure 3. Using Java Object Serialization to make a deep copy
Unfortunately, this approach has some problems, too:
It will only work when the object being copied, as well as all of the other objects references directly or indirectly by the object, are serializable. (In other words, they must implement java.io.Serializable.)

String empty check is more easy now with JDK6

Prior to JDK 6, we can check if a string is empty in 2 ways:


if(s != null && s.length() == 0)
if(("").equals(s))

Checking its length is more readable and may be a little faster. Starting from JDK 6, String class has a new convenience method isEmpty():

boolean isEmpty()
Returns true if, and only if, length() is 0.

It is just a shorthand for checking length. Of course, if the String is null, you will still get NullPointerException.
I don't see much value in adding this convenience method. Instead,
I'd like to see a static utility method that also handle null value:

public static boolean notEmpty(String s) {
return (s != null && s.length() > 0);
}


Another option, use StringUtils.isEmpty(String str) of Apache commons , can be downloaded from

http://commons.apache.org/

It checks for null string also and return true for empty

public static boolean isEmpty(String str) {
return str == null str.length() == 0;
}

Common Errors in Setting Java Heap Size

Two JVM options are often used to tune JVM heap size: -Xmx for maximum heap size, and -Xms for initial heap size. Here are some common mistakes I have seen when using them:

• Missing m, M, g or G at the end (they are case insensitive). For example,

java -Xmx128 TestProgram
java.lang.OutOfMemoryError: Java heap space

The correct command should be: java -Xmx128m TestProgram. To be precise, -Xmx128 is a valid setting for very small apps, like HelloWorld. But in real life, I guess you really mean -Xmx128m

• Extra space in JVM options, or incorrectly use =. For example,

java -Xmx 128m TestProgram
Invalid maximum heap size: -Xmx
Could not create the Java virtual machine.
java -Xmx=512m HelloWorld
Invalid maximum heap size: -Xmx=512m
Could not create the Java virtual machine.

The correct command should be java -Xmx128m TestProgram, with no whitespace nor =. -X options are different than -Dkey=value system properties, where = is used.

• Only setting -Xms JVM option and its value is greater than the default maximum heap size, which is 64m. The default minimum heap size seems to be 0. For example,

java -Xms128m TestProgram
Error occurred during initialization of VM
Incompatible initial and maximum heap sizes specified

The correct command should be java -Xms128m -Xmx128m TestProgram. It's a good idea to set the minimum and maximum heap size to the same value. In any case, don't let the minimum heap size exceed the maximum heap size.

• Heap size is larger than your computer's physical memory.For example,

java -Xmx2g TestProgram
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

The fix is to make it lower than the physical memory: java -Xmx1g TestProgram

• Incorrectly use mb as the unit, where m or M should be used instead.

java -Xms256mb -Xmx256mb TestProgram
Invalid initial heap size: -Xms256mb
Could not create the Java virtual machine.

• The heap size is larger than JVM thinks you would ever need. For example,

java -Xmx256g TestProgram
Invalid maximum heap size: -Xmx256g
The specified size exceeds the maximum representable size.
Could not create the Java virtual machine.

The fix is to lower it to a reasonable value: java -Xmx256m TestProgram

• The value is not expressed in whole number. For example,
java -Xmx0.9g TestProgram
Invalid maximum heap size: -Xmx0.9g
Could not create the Java virtual machine.
The correct command should be java -Xmx928m TestProgram


How to set java heap size in Eclipse?
You have 2 options:

1. Edit eclipse-home/eclipse.ini to be something like the following and restart Eclipse.

-vmargs
-Xms64m
-Xmx256m

2. Or, you can just run eclipse command with additional options at the very end. Anything after -vmargs will be treated as JVM options and passed directly to the JVM. JVM options specified in the command line this way will always override those in eclipse.ini. For example,
eclipse -vmargs -Xms64m -Xmx256m

New IOException Constructors in JDK 6

In JDK 1.5 or earlier, IOException only has 2 constructors:
IOException() and IOException(String s).

So you can't pass a cause exception or throwable to these constructors. To do that, you will need to do something like this:

ZipException ze = new ZipException("Nested ZipException");
IOException e = new IOException("IOException with nested ZipException");
e.initCause(ze);
throw e;




In JDK 6, 2 additional constructors are added:

IOException(String s, Throwable cause)
IOException(Throwable cause)

So the following can compile and run fine in JDK 6 and later:


ZipException ze = new ZipException("Nested ZipException");
IOException e = new IOException(ze);
throw e;

but will fail to compile in JDK 1.5 or earlier:

c:\tmp > javac -version A.java
javac 1.5.0_06A.java:15: cannot find symbol
symbol : constructor IOException(java.util.zip.ZipException)
location: class java.io.IOException
IOException e = new IOException(ze);
^1 error

Tiger Provided option for getting various Thread States

Prior to Java 5, isAlive() was commonly used to test a threads state. If isAlive() returned false the thread was either new or terminated but there was simply no way to differentiate between the two. Starting with the release of Tiger (Java 5) you can now get what state a thread is in by using the getState() method which returns an Enum of Thread.States. A thread can only be in one of the following states at a given point in time.

NEW A Fresh thread that has not yet started to execute.
RUNNABLE A thread that is executing in the Java virtual machine.
BLOCKED A thread that is blocked waiting for a monitor lock.
WAITING A thread that is wating to be notified by another thread.
TIMED_WAITING A thread that is wating to be notified by another thread for a specific amount of time
TERMINATED A thread whos run method has ended.


The folowing code prints out all thread states.

public class ThreadStates{
public static void main(String[] args){
Thread t = new Thread();
Thread.State e = t.getState();
Thread.State[] ts = e.values();
for(int i = 0; i < ts.length; i++){
System.out.println(ts[i]);
}
}
}

Heroku Custom Trust Store for SSL Handshake

  Working with Heroku for deploying apps (java, nodejs, etc..) is made very easy but while integrating one of the service ho...