Archive for the ‘Java’ Category

Java 5 enums can be compared with ==

Thursday, September 6th, 2007

Java Enum instances are singletons. This seems to be not clearly documented by Sun (at least I found it difficult to find). But it’s the case.

What this means is that it’s possible to compare enumerated types by identity, which is cool for readability. (And it means that the switch statement works.)

You don’t have to write this:

if (PurchaseState.complete.equals(anItem.getPurchaseState()) { ...

You can write:

if (anItem.getPurchaseState() == PurchaseState.complete) { ...

This is documented here in the “discussion” section.

Java: List<X> or X[] ?

Thursday, July 12th, 2007

Since the creation of Java 1.5, one’s been able to parametrize classes using generics, with a syntax similar to C++ templates.

Before Java 1.5, I would always return simple list data structures as arrays. This was

  • Type-safe (e.g. User[] as opposed to List; the former one knows what’s in the collection, in the latter one doesn’t)
  • One could find out the length of the collection with array.length (in contrast to C arrays)

But since Java 1.5, one has a choice. One could use the Java collections framework, now supporting generics, or still use arrays.

Perhaps it’s because I don’t like change, but I would still advocate using arrays as opposed to Lists:

  • The generic information is thrown away at compile-time, so a List<X> and List<Y> look the same at run-time, whereas X[] and Y[] do not. Introspection, and getting exceptions at the time of a wrong array cast, and not later, are the benefits here.
  • You can easily create an array declaratively. int[] x = new int[] { 1, 2 }; You can’t do the same with the collections frameworks.
  • I’m sure arrays are faster
  • Arrays are also simpler. I think one should, given two solutions to the same problem, nearly always take the simpler unless there’s a clear benefit of the more complex solution (which I don’t see in this case)

Maybe the point about faster and simpler aren’t really relevant points these days. But collections are still the sort of things which one accesses in inner loops. Consider the ways in which X[] is faster than List<X>:

  • To iterate over the collection, with List<X> you need to create an Iterator. This also happens if you use the “foreach” construct.
  • To get a particular element, or to get the length, you have to call methods, like aList.get(3).

It has been said that using Iterators is preferable to using a for loop over array indexes, for software design reasons. This may be the case in some special situations, but I really don’t think it’s an advantage in common usage.

  • One can iterate over an array or collection with the Java 1.5 “foreach” keyword: so in this case the source code looks the same.
  • The code “for (i=0; i<array.length; i++)”, i.e. non-iterator code, is not really difficult to write or difficult to read.

Hibernate / Boolean Fields / MySQL 5.0

Wednesday, July 4th, 2007

There’s a problem persisting boolean fields using Hibernate 3.2.2 to MySQL 5.0, if you allow Hibernate to generate your schema, and you leave Hibernate to generate the schema in the default way. It works fine on MySQL 4.1 and it doesn’t matter if you use boolean (primitive) or Boolean (object) types for the fields.

with a class such as:

public class MyObject {
   protected boolean myField;
   public boolean getMyField() { return myField; }
   public void setMyField(boolean x) { myField = x; }
}

and a Hibernate mapping such as:

<property name="myField" column="my_field" not-null="true" />

and allow Hibernate to generate the schema on startup, e.g. by writing the following in the “hibernate.cfg.xml” file:

<property name="hbm2ddl.auto">create</property>

Against MySQL 4.1 this all works, and the column has the data type tinyint(1). But in MySQL 5.0 the data type is bit(1) (which seems logical enough) but Hibernate then throws the following unhelpful exception upon every insert:

could not insert: [com.company.MyObject]
org.hibernate.exception.DataException: could not insert: [com.company.MyObject]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:77)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
....
Caused by: java.sql.SQLException: Data too long for column 'my_field' at row 1
at ....

The solution is to change the Hibernate mapping for the field to this:

<property name="myField" not-null="true" >
   <column sql-type="BOOLEAN" not-null="true" name="my_field" />
</property>

Then the field is generated as tinyint(1) and then it all works fine again.

Generate Javadoc HTML only for public members

Monday, July 2nd, 2007

In Java there are four protection levels which members (fields and methods) can have:

  1. Private
  2. Protected
  3. Package-level
  4. Public

Any member can have Javadoc (including private members).

But when one generates the Javadoc, which protected levels should be included?

Generated Javadoc is used by humans. These humans are probably not you. And thus are probably clients of your classes, either within or outside of your organization. It’s possible, although unlikely, that they may be able to access package-level members. It’s possible they may need to subclass your class, although in (nearly) all cases I can conceive of, they won’t do that without looking at your source code.

Javadoc should be simple to understand. There’s simply a lot of potentially documentable stuff going on in a class, which is capable of reducing simplicity. Setters which only Hibernate needs to see (private), or which only your factories in your package need to see (package-level).

Javadoc should therefore only be generated only for public attributes. That’s what Sun’s JDK docs do as well (for example you don’t see any protected or private stuff here). And there’s an additional benefit of simplicity is that if this is the only level for which the Javadoc is being generated, it doesn’t even state the protection level in the summary, so you see “int getX()” in the method list as opposed to “public int getX()”.

This can be achieved with the “-public” option to the Javadoc generation program. In Netbeans 5.5, right-click on the project in the “projects” tab, select the menu item “properties”, go to the “documentation” entry under the “build” entry, and enter “-public” in the “additional javadoc options” field.