Java Minutiae - @return
Often I see Javadoc with only an
@return
tag:
/**
* @return the current user assigned to make the delivery, or {@code null}
* if no such assignment has been made.
*/
public User getDeliveryPerson();
Unfortunately, the
javadoc
command line tool doesn't handle this format particularly well. Since the method has no summary, nothing is listed in the Javadoc overview:
Instead, whenever your method has no description, promote the
@return
tag into the method description by replacing
@return
with the word "Returns":
/**
* Returns the current user assigned to make the delivery, or {@code null}
* if no such assignment has been made.
*/
public User getDeliveryPerson();
This makes the Javadoc report much better:
Thanks to
Kevinb for the tip.
# posted by Jesse Wilson
on Friday, February 29, 2008
0 comments
post a comment
Guice commands
I recently checked in a new
Guice extension called commands. The goal is simple - make it possible to modify your modules at runtime.
But modules aren't naturally data, they're more like code:
Module module = new AbstractModule() {
protected void configure() {
bind(Soda.class).to(Coke.class);
bind(Snack.class).to(BuffaloRanchDoritos.class);
}
};
How can I convert this executable chunk of code into a manipulatable datastructure? Since Guice is built-on a well-defined API, this wasn't too difficult. I created a custom
Binder
that recorded the method calls into it made by the modules. I wrapped that in an API that converts the method calls into
Command
objects:
CommandRecorder commandRecorder = new CommandRecorder(new FutureInjector());
List<Command> commands = commandRecorder.recordCommands(module);
The
Command
interface has different implementation for each method
* on
Binder
. There's
BindConstantCommand
,
BindScopeCommand
,
RequestStaticInjectionCommand
and several others. The interface supports
visitors, so manipulating commands with type safety is easy.
Finally, there's a class called
CommandReplayer
that can convert a list of commands back into a module. By extending the template methods, you can rewrite commands while you replay them:
CommandReplayer rewriter = new CommandReplayer() {
@Override public <T> void replayBind(Binder binder, BindCommand<T> command) {
Key<? extends T> target = command.getTarget().getKey(null);
if (Key.get(Soda.class).equals(target)) {
binder.bind(Soda.class).to(Pepsi.class);
} else {
super.replayBind(binder, command);
}
}
};
Module rewrittenModule = rewriter.createModule(commands);
The last thing left to do is to build an injector from the rewritten module. It works!
Injector injector = Guice.createInjector(rewrittenModule);
assertEquals(new Pepsi(), injector.getInstance(Soda.class));
We're using commands in a soon-to-be-released test library. I suspect other Guice users will come up with more interesting uses of commands. If you're hacking on Guice, consider using
commands when you need to tweak a module.
# posted by Jesse Wilson
on Thursday, February 28, 2008
1 comments
post a comment
Java Minutiae - Class.toString()
Class.toString() doesn't return what you'd expect:
assertEquals("java.lang.Integer", Integer.class.toString());
Instead, it prefixes the fully-qualified classname with "class " for classes, "interface " for interfaces and probably "enum " and "annotation " elsewhere. You need to call
getName
or
getSimpleName()
to get what you usually want.
assertEquals("java.lang.Integer", Integer.class.getName());
assertEquals("Integer", Integer.class.getSimpleName());
What can I learn from this? The
toString()
value is important to the usability of an API. With
toString
, it's often better to be terse rather than complete.
# posted by Jesse Wilson
on Thursday, February 28, 2008
3 comments
post a comment
Java.net Poll on Closures
Java.net is having a
poll on which version of closures is preferred for Java 7. I think this is a great opportunity for
First-Class Methods (FCM) to get some attention as a worthy contender.
Closures offer us the opportunity to make our Java
code simpler by making the Java
language more complex. The tradeoff is - how much simpler will our programs get, and how much more complex will the language get? I feel that First-Class Methods presents the best balance between language complexity and code simplicity.
First Class Classes
Do you ever use Class objects in your application? For example, to instantiate a logger:
public class RealDeliveryService {
private static final Logger logger = Loggers.forClass(RealDeliveryService.class);
...
}
... or to bind a type with Guice:
public void configure() {
bind(DeliveryService.class).to(RealDeliveryService.class);
bind(User.class).toProvider(UserProvider.class);
...
}
Class literals are powerful, typesafe, and easy to use. FCM takes the power of Class literals and extends it to methods and fields.
First Class Methods
With this, much boilerplate code vanishes. Consider sorting Deliveries by price:
List<Delivery> deliveries = ...
Comparator<Delivery> orderByPrice = new Comparator<Delivery>() {
public int compare(Delivery a, Delivery b) {
return a.getPrice().compareTo(b.getPrice());
}
}
Collections.sort(orderByPrice, deliveries);
With FCM, we just create a comparator from the
getPrice
method:
List<Delivery> deliveries = ...
Comparator<Delivery> orderByPrice = MethodComparator.newInstance(Delivery#getPrice());
Collections.sort(orderByPrice, deliveries);
FCM can dramatically reduce boilerplate throughout your application:
- If you're writing a Swing app, you'll be able to specify a no-argument method to
invokeLater
, rather than defining an anonymous Runnable
. - If you're writing a web app, FCM will lend additional typesafety to your libraries like Struts 2.
- And FCM invites a new generation of frameworks and tools to be created. Terse like ruby, typesafe like Java.
Help FCM Gain Mindshare
Please,
familiarize yourself with the proposals and
vote for a better Java.
# posted by Jesse Wilson
on Sunday, February 17, 2008
0 comments
post a comment
Java Minutiae - Array class literals
Guice loves class literals:
bind(Foo.class)
.toProvider(FooProvider.class);
Today I found out that there's a simple syntax for declaring a literal array. Just add an extra pair of square brackets:
bind(Foo[].class)
.toProvider(FooArrayProvider.class);
# posted by Jesse Wilson
on Tuesday, February 12, 2008
0 comments
post a comment
Java Minutiae - Arrays.hashCode()
I'm working on a simple API that deals with raw arrays - yuck!
Did ya know that
Arrays.hashCode(a)
is
the same as
Arrays.asList(a).hashCode()
? Somebody smart made it easy to migrate from arrays to Lists.
# posted by Jesse Wilson
on Tuesday, February 12, 2008
0 comments
post a comment
Anal Retentive Java Style - Annotation Placement
A shared codebase means a shared styleguide. An issue that's come up a lot recently is where to put the damn
@Override
tag, and similar marker annotations.
Above:
@Override
public String toString() {
return "Delivery " + id;
}
Inline
@Override public String toString() {
return "Delivery " + id;
}
Here's my claim for writing the annotation inline.
@Override
isn't much different from
final
. They each constrain the method's inheritance - that it must override, or that it mustn't be overridden. Since
final
was thought up when the Java language was being designed, it gets to be a language feature - whereas
@Override
is an extension. If the Java language were to be designed again,
final
would probably be
@Final
.
More practically, I don't think
@Override
is more important than the other modifiers. On it's own line, it's almost like the annotation is somehow more important than say, the method name, which has to share its space with the other modifiers.
So put
@Override
beside
public
. It's just another modifier.
# posted by Jesse Wilson
on Friday, February 01, 2008
2 comments
post a comment