Variance4J provides the declaration-site variance annotations for Java like in C#.
- Write
@Inand@Outin your code. - Compile your code with Variance4J.
javac -cp path/to/variance4j.jar Foo.java
- Check
Enable project specific settingsinProperties > Java Compiler > Annotation Processing. - Ensure
Enable annotation processingis checked inProperties > Java Compiler > Annotation Processing. - Check
Enable project specific settingsinProperties > Java Compiler > Annotation Processing > Factory Path. - Add variance4j.jar to
Properties > Java Compiler > Annotation Processing > Factory Path. - Add variance4j.jar to
Properties > Java Build Path > Libraries.
It can report the errors at compile time if the return type or the parameter types of the methods are illegal.
interface Foo<@Out T> {
void bar(T t); // Error
void baz(Consumer<? super T> consumer); // OK
}It cannot eliminate Wildcards: ? extends and ? super. They are still necessary to realize variances in Java even if you use @In and @Out.
Foo<Cat> cat = ...;
Foo<Animal> animal = car; // ErrorFoo<Cat> cat = ...;
Foo<? extends Animal> animal = car; // OKIt is difficult to use Wildcards correctly. For example, the following code has a problem.
interface Foo {
Comparator<Integer> getComparator();
}It is impossible to declare interface Bar extends Foo with Comparator<Number> getComparator() with the Foo above. The better one is the below.
interface Foo {
Comparator<? super Integer> getComparator();
}With @In and @Out, we never wonder which to use ? super or ? extends. The following simple rule is useful to decide which Wildcard to apply.
- If declared as
@In, use? super. - If declared as
@Out, use? extends. - If declared without
@Innor@Out, neither? supernor? extendsis necessary.
/* Declaration-site */
// Contravariant for T, Covariant for R
interface Function<@In T, @Out R> {
R apply(T t);
}/* Use-site */
// Variables
Function<? super String, ? extends Number> function = ...;
// Parameter Types
void foo(Function<? super String, ? extends Number>) { ... }
// Return types
Function<? super String, ? extends Number> bar() { ... }If Variance4J provided just the annotations, @In and @Out, it would be hard to declare types of methods legally. Variance4J provides the annotation processor to check the types so that programmers never declare illegal methods with @In and/or @Out.
- Java 8
