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

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: