Playing With args4j Part 5 — Safe setters

This is the fifth part of the Playing With args4j series. For your convenience you can find other parts in the table of contents in Part 1 – Mixins

There is one more problem with our setters — they are not type safe. This means that we may have integer parameter:

And then we can call this:

This compiles and crashes in runtime:

Can we do something about it? Currently our setter signature is:

This means that the line parameters.set(parameters::parameter, "1.23") is actually treated as parameters.< Object>set(parameters::parameter3, "1.23") thanks to target typing and covariant return type in method references. See more in http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html.

To fix that we need to stop covariance in some way. We can do this by enforcing the type T to be invariant by putting it in contravariant position. First trick is:

Then we set the parameter in this way:

Because we return the Consumer< T> where T is in both covariant and contravariant position, the compiler cannot use Object as T and we are safe again. However, this is cumbersome as we need to use accept method.

There is yet another trick. We need to separate type parameters:

Thanks to that we can still call:

And when we pass String we get:

So the final code is:

Base type for mixin:

Actual interface with parameters:

Concrete parameters implementation:

Helper methods for accessing the lambda instance:

Parser for custom setters:

Custom setter:

And finally, execution:

When you execute this as:

You get the following output: