'. '

Erasure

From APIDesign

(Difference between revisions)
Jump to: navigation, search
Line 16: Line 16:
The only question is whether code compiled against old [[API]] will link against new [[API]]? Surprisingly (at least for those who remember that [[Contravariance]] is not [[BinaryCompatibility|binary compatible]]) this change is also binary compatible - e.g. it is fully [[BackwardCompatible]]! This is caused by the [[Erasure]] of generic type information. When compiled into binary form, the signature method is just {{JDK|java/util|Set}} (without any additional generic information), so the [[JVM]] sees no change between version 1.0 of the API and version 2.0. Both work on {{JDK|java/util|Set}}s.
The only question is whether code compiled against old [[API]] will link against new [[API]]? Surprisingly (at least for those who remember that [[Contravariance]] is not [[BinaryCompatibility|binary compatible]]) this change is also binary compatible - e.g. it is fully [[BackwardCompatible]]! This is caused by the [[Erasure]] of generic type information. When compiled into binary form, the signature method is just {{JDK|java/util|Set}} (without any additional generic information), so the [[JVM]] sees no change between version 1.0 of the API and version 2.0. Both work on {{JDK|java/util|Set}}s.
 +
 +
<comments/>
 +
 +
PS: Tribute for this inventive use of generic type [[erasure]] belongs to Tomáš Zezula.

Revision as of 18:22, 19 October 2011

It is well known that while Covariance and Contravariance work OK from the source compatibility point of view in Java, but they are not very BackwardCompatible from the binary point of view. As the binary compatibility is one of the most important ones for a compiled language like Java, one could think, that usage of Covariance or Contravariance is impossible. However it is not (at least not completely) - with the help of erasure of generic type information in Java one can use both-variances to own benefits.

Imagine there is a simple method that operates on set of integers:

Code from Erasure.java:
See the whole file.

public static boolean arePositive(Collection<? extends Integer> numbers) {
    for (Integer n : numbers) {
        if (n <= 0) {
            return false;
        }
    }
    return true;
}
 

Any user of such API can call this method with a set of Integers:

Code from ErasureTest.java:
See the whole file.

List<Integer> oneToTen = Arrays.asList(2, 4, 6, 8, 10);
boolean positive = arePositive(oneToTen);
System.err.println("positive = " + positive);
assert positive : "All the numbers are positive: " + oneToTen;
 

Later somebody decides that it would be nice to change method to accept not only integers, but all numbers and creates new version of the API with the same method, but accepting wider parameter types:

Code from Erasure.java:
See the whole file.

public static boolean arePositive(Collection<? extends Number> numbers) {
    for (Number n : numbers) {
        if (n.doubleValue() <= 0.0d) {
            return false;
        }
    }
    return true;
}
 

Obviously, this is source compatible as this is contravariant extension of the range of values the method can absorb. Without a doubt this is also functionally compatible, as the code now calls doubleValue method and this one was available on Integers as well, so there is no change in the runtime contract.

The only question is whether code compiled against old API will link against new API? Surprisingly (at least for those who remember that Contravariance is not binary compatible) this change is also binary compatible - e.g. it is fully BackwardCompatible! This is caused by the Erasure of generic type information. When compiled into binary form, the signature method is just Set (without any additional generic information), so the JVM sees no change between version 1.0 of the API and version 2.0. Both work on Sets.

<comments/>

PS: Tribute for this inventive use of generic type erasure belongs to Tomáš Zezula.

Personal tools
buy