Sunday, 3 August 2008

Java abstract enumeration and java.lang.Class.isEnum() problem

One of new features in Java 1.5 is direct support of enumeration using enum keyword. According to this the new method isEnum() has been added to java.lang.Class class (which is part of Java Reflections API). The problem is that the isEnum method doesn’t always behave as you would expect.

Let’s start with the following Java code:

public class MainTest {

// Enum with custom constructor
enum EnumPrivate {

VALUE(1);

private int value;

private EnumPrivate(int value) {
this.value = value;
}

public int getValue() {
return value;
}

}

// Enum having an abstract method
enum EnumAbstract {

VALUE(1) {
public int getRandomValue() {
return 10;
}
};

private int value;

private EnumAbstract(int value) {
this.value = value;
}

public abstract int getRandomValue();

}


/**
* @param args
*/
public static void main(String[] args) {
System.out.println(EnumPrivate.VALUE.getClass().isEnum());
System.out.println(EnumAbstract.VALUE.getClass().isEnum());
}

}


Both EnumPrivate and EnumAbstract are not simple enums. The first one has custom constructor (which must be private) and the second an abstract method which must be implemented in each enum’s value. Let’s try to run the main method. You would probably expect “true” twice in the output but you will get the “true” and “false”. It’s quite strange isn’t it?

Let’s try to find out what the java.lang.Class documentation says about isEnum() method. You would find the following:

Returns true if and only if this class was declared as an enum in the source code.

The description of the method doesn’t say anything special about enums with abstract methods so let’s find the isEnum method’s source code in JDK. You could find the following:

public boolean isEnum() {
return (this.getModifiers() & ENUM) != 0 &&
this.getSuperclass() == java.lang.Enum.class;
}


You can see that isEnum returns true if the super class of the class represeting an enum is java.lang.Enum class (we will not bother about modifier) but what's the supeclass of the our enum class? How to find out? The answer is that they are compiled to ordinary Java classes in the same way as any other class so let’s try to decompile them. You would get the result similar to the following:

final class EnumPrivate extends Enum
{

public static final EnumPrivate VALUE;
private int value;
private static final EnumPrivate ENUM_VALUES[];

static
{
VALUE = new EnumPrivate("VALUE", 0, 1);
ENUM_VALUES = (new EnumPrivate[] {
VALUE
});
}

private EnumPrivate(String s, int i, int value)
{
super(s, i);
this.value = value;
}



}

abstract class EnumAbstract extends Enum
{

public static final EnumAbstract VALUE;
private int value;
private static final EnumAbstract ENUM_VALUES[];

static
{
VALUE = new EnumAbstract("VALUE", 0, 1) {

public int getRandomValue()
{
return 10;
}

};
ENUM_VALUES = (new EnumAbstract[] {
VALUE
});
}

private EnumAbstract(String s, int i, int value)
{
super(s, i);
this.value = value;
}

public abstract int getRandomValue();

EnumAbstract(String s, int i, int j, EnumAbstract EnumAbstract)
{
this(s, i, j);
}

….

}


If you compare EnumPrivate and EnumAbstract then you should find the problem. EnumPrivate extends the Enum and it’s VALUE is EnumPrivate. EnumAbstract extends Enum as well but because it has the abstract method it must be the abstract class. VALUE is then anonymous inner child class of the EnumAbstract so its superclass is not Enum but EnumAbstract!

As you can see enums (or isEnum) should be corrected a bit in the future versions of Java. You have got two enumerations according to specification but only one of them is correctly recognized as enumeration.

You can find many issues when using enums with abstract methods in combination with third party libraries (or applications). Assume a library for automatic converting standard Java types to e.g. String. The library will get the Object and then need to find out the type of object to correctly do the conversion to String. If the library relies on the isEnum() method to recognize enums then it won’t correctly recognize your enum with abstract method value as enum. This happened to me and I spend a few hours searching for the problem and that’s the reason why I decided to share my experience with you.

Monday, 30 June 2008

State design pattern in Java

State design pattern is extremely useful when you need a state class. Typical example is a class making a connection to a server (check POP3 client tutorial for example). The class then has two states – connected and disconnected (which is the default state). In the class you would need to check for the state at many places. Let’s imagine that your class doesn’t have just two states but four or ten. You would find then many constructs similar to the following in your class:

public class Door {

private DoorStates state;

private void someMethod() {
// ....
switch (state) {
case CLOSED: // .....
case CLOSING: // .....
case OPENED: // .....
case OPENING: // .....
}
// ...
}

}


The main reasons for State design pattern are extensibility and simplification of the code.

Now I would like to tell you how to implement State designer pattern. The first thing you need to do is to figure out states which your class (let’s call it main class) can have. Let’s have a class handling a connection to a server. The class can certainly have states connected and disconnected. Each state is implemented using its own class (let’s call it state class) and all state classes have one identical ancestor (either interface or abstract class). In state class would be methods that behave differently in each state (the methods that would contain switch (state) { … } ). At first let’s see the main class:

public class Connection {

// state class instance reference
private ConnectionState state;

// list of all possible states
protected final ConnectionState CONNECTED = new ConnectionStateConnected(this);
protected final ConnectionState DISCONNECTED = new ConnectionStateDisconnected(this);

public Connection() {
// default state is disconnected
state = DISCONNECTED;
}

public void connect() {
state.connect();
}

public void disconnect() {
state.disconnect();
}

public boolean isConnected() {
return state.isConnected();
}

// called by a state class to set new state to this connection
protected void setState(ConnectionState state) {
this.state = state;
}

}


The first in the class is the state attribute that holds the actual state of the main class. Next attributes CONNECTED and DISCONNECTED are all possible states that the class can have. Please notice that they are protected. That is because of the state classes which need access them as you will see later. All state methods just delegate the call to the state class.

Now let’s see the ancestor of the all state classes:

public abstract class ConnectionState {

// childs need to have access to the connection instance too
protected final Connection connection;

public ConnectionState(Connection connection) {
this.connection = connection;
}

public abstract void connect();

public abstract void disconnect();

public abstract boolean isConnected();

}


Each state class has to implement the abstract class above. The only interesting thing is the connection attribute. A state class usually need somehow change state of the main class thus it has a main class reference so that the setState(…) method can be called in a state class.

I said that the connection class would have two states – connected and disconnected. We would then have two implementations of the abstract state class named ConnectionStateConnected and ConnectionStateDisconnected.

public class ConnectionStateConnected extends ConnectionState {

public ConnectionStateConnected(Connection connection) {
super(connection);
}

public void connect() {
throw new IllegalStateException("Already connected");
}

public void disconnect() {
// disconnect somehow

// finally set disconnected state of the connection instance
connection.setState(connection.DISCONNECTED);
}

public boolean isConnected() {
return true;
}

}


Please notice how the state class changes the state of the main class in disconnect() method.

public class ConnectionStateDisconnected extends ConnectionState {

public ConnectionStateDisconnected(Connection connection) {
super(connection);
}

public void connect() {
// connect somehow ...

// finally set connected state of the connection instance
connection.setState(connection.CONNECTED);
}

public void disconnect() {
throw new IllegalStateException("Already disconnected");
}

public boolean isConnected() {
return false;
}

}


You have to carefully figure out what to do if a state is called but it shouldn’t be. Example can be calling disconnect() method when there is no connection. You can either throw IllegalStateException or just log warning message wherever.

As you can notice … adding a new state is very simple task. You just add new child of the abstract state class, add new attribute representing the new state to the main class and that’s all.

You can download source codes here: http://rapidshare.com/files/126155409/stateDesignPattern.zip

Sunday, 8 June 2008

How to call private constructor/method from outside in Java

As you certainly know, one of the OOP’s features is encapsulation. Java has private keyword to specify encapsulated constructors, methods or attributes. These methods and attributes should not be accessible from the rest of the world (they are not part of the API) and Java doesn’t allow you to do that ordinarily.

You can however use Java reflections API to access any private method, field or constructor of any class and it’s really very simple task. Let’s assume we have got the following simple class:
public class Test {

private Test() {
System.out.println("private constructor has been called");
}

private void test() {
System.out.println("private test() method has been called");
}

}
The class has private constructor and method (notice that such class is worthless because there is no way how to ordinarily get or create instance of it). Now I’ll show you how to get instance of the class using Java reflections and call the private method:
public class Main {

public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, SecurityException, NoSuchMethodException {

Class<Test> clazz = Test.class;

Constructor<Test> c = clazz.getDeclaredConstructor((Class[])null);
c.setAccessible(true); //hack
Test test = c.newInstance((Object[])null);

Method privateMethod = clazz.getDeclaredMethod("test", (Class[])null);
privateMethod.setAccessible(true); //hack
privateMethod.invoke(test, (Object[])null);
}

}
If you hadn’t called the setAccessible(true) method you would have got the java.lang.IllegalAccessException indicating that you call a method/constructor which is not meant to be called from outside.

Java reflections breaks OOP in many ways and you should very rarely use its “special” features like accessing private methods in your projects.