The interesting FuntionalJ library fills in a gap with reflective function objects while waiting for JDK7 closures. With flavors of C++ functors and Python zip
and tuples, FuntionalJ is a gem.
Tuesday, August 29, 2006
Filling in the Java closure gap
Tuesday, August 22, 2006
Two new toys to try out
Today I'm looking at two new web toys:
- GetOpenID, an OpenID provider (more on OpenID from the Wikipedia).
- Schtuff, a public wiki service with my poking at it.
Getting started on JRuby, a great post
Ola Bini has a great post on getting started with JRuby on Windows, The JRuby Tutorial #1: Getting started, followed up with more excellent posts in the JRuby tutorial series.
Monday, August 21, 2006
Mapping a Java bean
This is a straight-forward code post.
public class BeanMap<T> extends AbstractMap<String, Object> { private final T bean; private final Set<PropertyDescriptor> descriptors; public BeanMap(final T bean) throws IntrospectionException { this.bean = asNotNull(bean, "Missing bean"); final Set<PropertyDescriptor> descriptors = new HashSet<PropertyDescriptor>(); for (final PropertyDescriptor descriptor : getBeanInfo(bean.getClass()).getPropertyDescriptors()) // Only support simple setter/getters. if (!(descriptor instanceof IndexedPropertyDescriptor)) descriptors.add(descriptor); this.descriptors = unmodifiableSet(descriptors); } public Set<Entry<String, Object>> entrySet() { return new BeanSet(); } @Override public Object get(final Object key) { return super.get(checkKey(key)); } @Override public Object put(final String key, final Object value) { checkKey(key); for (final Entry<String, Object> entry : entrySet()) if (entry.getKey().equals(key)) return entry.setValue(value); return null; } @Override public Object remove(final Object key) { return super.remove(checkKey(key)); } private String checkKey(final Object key) { // NB - the cast forces CCE if key is the wrong type. final String name = (String) key; if (!containsKey(asNotNull(name, "Missing key"))) throw new IllegalArgumentException("Bad key: " + key); return name; } private class BeanSet extends AbstractSet<Entry<String, Object>> { public Iterator<Entry<String, Object>> iterator() { return new BeanIterator(descriptors.iterator()); } public int size() { return descriptors.size(); } } private class BeanIterator implements Iterator<Entry<String, Object>> { private final Iterator<PropertyDescriptor> it; public BeanIterator(final Iterator<PropertyDescriptor> it) { this.it = it; } public boolean hasNext() { return it.hasNext(); } public Entry<String, Object> next() { return new BeanEntry(it.next()); } public void remove() { it.remove(); } } private class BeanEntry implements Entry<String, Object> { private final PropertyDescriptor descriptor; public BeanEntry(final PropertyDescriptor descriptor) { this.descriptor = descriptor; } public String getKey() { return descriptor.getName(); } public Object getValue() { return unwrap(new Wrapped() { public Object run() throws IllegalAccessException, InvocationTargetException { final Method method = descriptor.getReadMethod(); // A write-only bean. if (null == method) throw new UnsupportedOperationException( "No getter: " + descriptor.getName()); return method.invoke(bean); } }); } public Object setValue(final Object value) { return unwrap(new Wrapped() { public Object run() throws IllegalAccessException, InvocationTargetException { final Method method = descriptor.getWriteMethod(); // A read-only bean. if (null == method) throw new UnsupportedOperationException( "No setter: " + descriptor.getName()); final Object old = getValue(); method.invoke(bean, value); return old; } }); } } private static interface Wrapped { Object run() throws IllegalAccessException, InvocationTargetException; } private static Object unwrap(final Wrapped wrapped) { try { return wrapped.run(); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (final InvocationTargetException e) { // Javadocs for setValue indicate cast is ok. throw(RuntimeException) e.getCause(); } } }
The idea is simple: give the Java getter/setter idiom a Map
interface. Commons Beanutils already does this but with a significant difference.
My example class is very brittle. It doesn't like null
, wrong classes or missing keys. And in a brittle language like Java, this is a good thing. This kind of brittleness finds bugs quickly following the venerable fail-fast principle.
Avoid code which returns null
or silently converts wrong-class arguments. You pay now in return for a clear conscience in the long term. I have better things to do with my time than debug NullPointerException
s.
Thursday, August 17, 2006
Class literal woes
In Bitten by the class literal change in Tiger Michael Nascimento writes about the surprising impact of JDK5 changing the rules for Foo.class
. As simple as that.
Amazing how such a small change can have ramifications. This is food for thought when making a "small change" as I often do while cleaning old code: How can it make a difference? should be asked as a real question, not as gesture to shrug off the nay-sayers.
May I follow my own advice!
Tuesday, August 15, 2006
Strange mini anti-pattern
It's strange seeing this:
List copy = (List) ((ArrayList) original).clone();
When this will do:
List copy = new ArrayList(original);
And as a bonus original need not be an ArrayList
.
Saturday, August 12, 2006
Ask, and ye shall receive
No sooner had I posted a Java enhanced for loop wish than a commenter pointed out the JGA and jga & the java 1.5 forloop. Shades of my beloved STL!
The JGA would be another excellent addition to the JDK and an encouragement to a well-proven style of programming common in many programming languages.
Friday, August 11, 2006
Read-only enhanced for loops in Java
I was just commenting on Paul Holser's blog about this small idiom using the Java enhanced for loop:
for (final T t : unmodifiable(collection)) { doSomethingWith(t); }
The plumbing is simple:
public static <T> Iterable<T> unmodifiable( final Collection<T> c) { return new Iterable<T>() { public Iterator<T> iterator() { // Presuming a static decorator method // akin to Collections.unmodifiableCollection() return unmodifiableIterator(c.iterator()); } }; }
Naturally, I wish Sun would add something like this to java.util.Collections
, but I am sure they get many, many requests for JDK additions. Adding in a cleaned up Jakarta Collections library would help.
Another example of this sort of thing is a filterable iterator:
for (final T t : filter(collection, filter) { // Only works on collection elements // accepted by the filter. doSomethingWith(t); }
Anyway, Paul has a lot of interesting ideas in store for Jaggregate 3.0.
UPDATE: An anonymous commenter made the observation that an immutable Iterable
is useless in an enhanced for loop. D'oh! I should not have overlooked that point when I used the enhanced for loop in my examples. However, the read-only property is still useful when you call iterator()
.
Thursday, August 10, 2006
Replace simulated Java lists with Iterable
While cleaning old Java code I ran across this pre-Tiger pattern several times:
class Thingies { private final List things = new ArrayList(); // Other useful fields public List getThings() { return Collections.unmodifiableList(things); } public void addThing(final Thing thing) { things.add(thing); } // Other useful methods }
Essentially the author intended to simulate a sort of List
decorated with other, useful information for a business object. Hiding the list internally is a Good Thing and helps abstraction. Using unmodifiableList
is great.
But with Tiger and generics, I can do better:
class Thingies implements Iterable<Thing> { private final List things = new ArrayList(); // Other useful fields public Iterator<Thing> iterator() { return things.iterator(); } public void addThing(final Thing thing) { things.add(thing); } // Other useful methods }
Now I can use the class with Tiger foreach syntax:
for (final Thing thing : instanceOfThingies) { // Do something with thing. }
This advice is available in many places on the Internet, and is good advice. But did you notice something wrong with the example? What happens with thingies.iterator().remove()
? I introduced an abstraction leak.
Let's fix the leak:
public Iterable<Thing> iterator() { return new Iterator<Thing>() { final Iterator<Thing> it = things.iterator(); public boolean hasNext() { return it.hasNext(); } public Thing next() { return it.next(); } public void remove() { throw new UnsupportedOperationException(); } }; }
Now if the caller decides to use thingies.iterator() directly, they still cannot modify the underlying list.
A neat trick
Continuing this theme, I also ran across a neat trick. The old code has a small class hierarchy which the simulated list managed. Typical usage:
class FourWheeler { } class Sedan extends FourWheeler { } class Pickup extends FourWheeler { } // In another class far, far away: final Iterator sedans = fourWheelers.getList().iterator(); while (sedans.hasNext()) { final Sedan sedan = (Sedan) it.next(); } // In yet another class even more far, far away: final Iterator pickups = fourWheelers.getList().iterator(); while (pickups.hasNext()) { final Pickups pickup = (Pickup) it.next(); }
The thing is, the four wheelers list manager only held one type of four wheeler at a time so the caller was safe in casting as long as they were careful in updating the list. But this is very wordy. One approach is to generify the list manager:
class FourWheelers<T extends FourWheeler> { private final List<T> list = new ArrayList<T>(); // Rest of class uses T instead of FourWheeler. }
This is a great approach to the problem for new code. But there is a smaller change one can make to the class that also works. Add a new method:
public Iterable<Sedan> sedans() { return new Iterable<Sedan>() { public Iterator<Sedan> iterator() { final Iterator it = list.iterator(); public boolean hasNext() { return it.hasNext(); } @SuppressWarnings({"unchecked"}) public Sedan next() { return (Sedan) it.next(); } public void remove() { throw new UnsupportedOperationException(); } } }; }
And likewise for Pickup
. You can abstract this common pattern to a base class and simplify the methods further:
public Iterable<Sedan> sedans() { return new FourWheelerIterable<Sedan>(list.iterator()); }
Usage is now like this with all the nasty casting hidden away:
// Back in a far, far away class. for (final Sedan sedan : fourWheelers.sedans()) { // Do something with sedan. }
UPDATE: Jörg has a great observation in the comments: you may need more than one kind of generic Iterable<T>
for a complex class.
Wednesday, August 09, 2006
Crossing generics and covariant returns
Quick: why doesn't this compile?
fred.setFoo(new Foo());
Ok, some context:
class Bob<Foo extends Foo> { private Foo foo; public void setFoo(final Foo foo) { this.foo = foo; } } class Fred extends Bob<Bar> { }
See it now? How about now:
class Foo { } class Bar extends Foo { } class Bob<NOTFOO extends Foo> { private NOTFOO foo; public void setFoo(final NOTFOO foo) { this.foo = foo; } } class Fred extends Bob<Bar> { }
Yes, it was a mean trick to name a generic parameter the same as the class it extends. Sensibly, SUN's javac complains "illegal forward reference". I had to reread several times the code this example came from before it finally clicked what had happened.
But enough; on to the meat of the post.
I was cleaning some code and noticed this mini-anti-pattern in many places:
class Bob { private Foo foo; public Foo getFoo() { return foo; } public void setFoo(final Foo foo) { this.foo = foo; } } class Fred extends Bob { } class SomewhereElse { public void doWork(final Fred fred) { final Bar bar = (Bar) fred.getFoo(); } }
This style is quite commmon in pre-generics Java where there are parallel inheritance hierarchies: Foo
goes with Bob
, Bar
goes with Fred
, et al, and all the common code is pushed down into the lowest base class. All that casting makes my eyes sore.
But using generics, I get the advantages of covariant returns without needing any extra coding:
class Bob<F extends Foo> { private F foo; public F getFoo() { return foo; } public void setFoo(final F foo) { this.foo = foo; } } class Fred extends Bob<Bar> { }
Now the syntax error I first posed is a real time-saver: instead of getting a ClassCastException
at runtime, I get a compile error when trying:
fred.setFoo(new Foo());
The correct call is now:
fred.setFoo(new Bar());
What are covariant returns? To get generic code like this to work right, Java picked up covariant returns for free:
class abstract NumberPicker { public abstract Number pickANumber(); } class IntegerPicker extends Base { public Integer pickANumber() { return 42; } }
Because an Integer
is a Number
, Java recognizes that declaring IntegerPicker
to return an Integer
for pickANumber()
satisfies the contract for NumberPicker
: covariant returns. Generics uses the same trick in the compile when narrowing the return type for getFoo()
in the first examples, or something near enough.
You can read more on this and other goodies in Angelika Langer's Java Generics FAQs.
Tuesday, August 08, 2006
SQL and XML and JDBC4 and you
I missed it when he first posted: Lance Anderson (lead for JDBC4) has an excellent post with short recipes on using XML and SQL with JDBC4, JDBC 4.0 SQLXML Interface. Just the sort of thing when one is poking around for an easy way to use the new XML features of JDBC4.
Friday, August 04, 2006
A refinement on constructor tidiness
Last year I wrote a post about using generics to improve constructor argument checking, Let generics make your Java constructor cleaner. Since then I have refined the example method, asNotNull
.
The original:
public static <T> T asNotNull(final T input) { if (input == null) throw new NullPointerException(); return parameter; }
And updated:
public static <T> T asNotNull( final T input, final String message) { if (null == input) throw new IllegalArgumentException(message); return input; }
There are two differences:
- I throw
IllegalArgumentException
instead ofNullPointerException
. In addition to this being arguably more correct for the semantics of those two exceptions, it is also more useful as I will know that anyNullPointerException
is because of a call on anull
object. - I use a message for the thrown exception—usually of the form "Missing variableName"—to aid in fixing the problem from the stack trace output.
Another reason for the changes are consistency. I make use of other "contract"-based methods such as asNotEmpty
, etc., who all throw IllegalArgumentException
with an explanatory message. The consistency makes it easier for other programmers to take up the methods into their own code.
Thursday, August 03, 2006
svnmerge
I wish I had known about svnmerge ages ago. Happily Ken Kinder explains simple use in a good article, Subversion merge tracking with svnmerge.
Wednesday, August 02, 2006
Doug Lea's list of Mustang concurrency changes
Doug Lea of java.util.concurrent
fame maintains the Concurrency JSR-166 Interest Site. One of the interesting links is to Sun bug activity related to JSR166, Concurrency or Collections.
Lea's bug list is very handy for watching for interesting Mustang changes in concurrency or collections as they happen. I only stumbled across the list today—thank Google—, and noticed the nifty Add @see newSetFromMap for Map implementations without Set implementations fix, which got me to look at java.util.Collections
again and check the new methods.
Serendipity strikes.
Javadoc generic type parameters
While looking at the new NavigableSet interface introduced into JDK 6 (Mustang), I noticed this in the class javadocs:
* @param <E> the type of elements maintained by this set * @since 1.6 */ public interface NavigableSet<E> extends SortedSet<E> {
Well, that is new. I've not seen a generic type parameter used with the @param tag before.
Looking at the documentation for Javadoc 1.5, apparently this feature has been around since generics started.
A quick comparison between the sources of java.util.Set for JDK 5 and JDK 6 shows that Sun has added @param tags to the generic collection classes in Mustang.
Unfortunately, IntelliJ IDEA 6.0 beta does not show these class generic tags in the class quickdocs, which is why I never noticed them before. Hopefully JetBrains fixes this at some point.
On the flip side, the JDK 6 javadoc tool does handle the tags. Witness java.util.Set for Mustang.
Tuesday, August 01, 2006
Java generics trick to work out parameter types
Another nifty trick I hadn't seen before which I ran across on the Hibernate page for their generic DAO classes:
public abstract class GenericHibernateDAO<T, ID extends Serializable> implements GenericDAO<T, ID> { private Class<T> persistentClass; private Session session; public GenericHibernateDAO() { this.persistentClass = (Class<T>) ((ParameterizedType) getClass() .getGenericSuperclass()) .getActualTypeArguments()[0]; } // ... }
Playing around with this revealed two things to me:
- This trick only works for concrete subclasses.
- The concrete subclass needs to not be generic, at least for the parameter in the interesting expression above.
So one could, for example, create a generic factory using this technique, although there does not seem on the surface to be much advantage:
public abstract class FactoryBase<T> { private final Class<T> type = (Class) ((ParameterizedType) getClass() .getGenericSuperclass()) .getActualTypeArguments()[0]; protected FactoryBase() { } public Class<T> getType() { return type; } public T create() throws IllegalAccessException, InstantiationException { // Real implementations do something more interesting // than imitate "new T()". return type.newInstance(); } } public class FredFactory extends FactoryBase<Fred> { } public class Main { public static void main(final String arguments) { final Fred fred = new FredFactory().create(); } }
How different is this from supplying a Class literal to the factory consturctor?
getGenericSuperclass()
seems one of those "back pocket" techniques: something I'll keep handy if the need arises but which I don't go out of my way to use.
UPDATE: A little playing shows that the minimal requirement is that the generic parameter whose index is queried with getActualTypeArguments() must be concrete; it is ok for another parameter to be a generic:
public class Bob<T, U> { final Class<T> tClass = getGenericTypeByIndex(getClass(), 0); private static Class getGenericTypeByIndex( final Class clazz, final int index) { return (Class) ((ParameterizedType) clazz .getGenericSuperClass()) .getActualTypeArguments()[index]; } } }
This snippet works ok as:
public class Fred<U> extends Bob<Fred, U> { public static void main(final String arguments) { new Fred<String>(); } }
But fails at runtime with a ClassCastException trying to turn a sun.reflect.generics.reflectiveObjects.TypeVariableImpl into a java.lang.Class:
public class Sally<T, U> extends Bob<T, U> { public static void main(final String arguments) { new Sally<Sally, String>(); } }