More Related Content


Primitives in Generics

  1. Primitives in Generics current state Ivan St. Ivanov
  2. Important disclaimer  This is work in progress  Likely to change  I am not an expert  Based on the State of Specialization document by Brian Goetz (see resources)  Same things apply to Value Types
  3. The state of generics  Only over reference types  If you want List<int>: List<Integer> intList = new ArrayList<>();  Performance penalty: Heade r Pointer Pointer Pointer Pointer Heade r int Heade r int Heade r int Heade r int
  4. But why?  Type erasure in generics public class Box<T> { private T value; public Box(T value) { this.value = value; } public T get() { return value; } }  At runtime T is erased to Object  No common “Object” for primitive and reference types
  5. Why erasure at all?  Use case: ◦ class C uses (or extends) class A ◦ class A is generified  Source and binary compatibility ◦ If class C does not compile: source incompatibility ◦ If class C should be recompiled to link: binary incompatibility  No flag day allowed!
  6. Possible approach  Project Valhalla  Compromise #1: current rules for generics should not be changed  Compromise #2: use separate approaches for representing different types  Compromise #3: subclass rules: ArrayList<int> <: List<int> YES List<int> <: List<Integer> NO List<int> <: List<?> NO List<int> <: List NO
  7. Proposed syntax  Introduce any type variable modifier public class Box<any T> { private T value; public Box(T value) { this.value = value; } public T get() { return value; } }  And then: Box<int> intBox = new Box<>(42);
  8. What about byte code? ErasedBox (for reference types) SpecialBox (for primitive types)
  9. Side note: translations  Heterogeneous translation ◦ Different runtime class for each different parametric type ◦ Hard to achieve data parametricity (Box<?>) ◦ C++ templates  Homogeneous translation ◦ Same runtime type for all different parametric types ◦ Java achieved it for reference types ◦ C# for reference and structural types ◦ .NET byte code can range over both types, Java - not
  10. Representation in bytecode  Erasure of reference types, specialization for primitives  Look again at SpecialBox usage site:  Class name augmented with specialization info
  11. Restrictions for any T  Cannot be converted or compared to null  Cannot be converted to Object or Object[]  Cannot be used as lock for synchronization  Cannot convert Foo<any T> to Foo<?> or Foo
  12. Available only for <any T>  Support for new T[size]  Use it where reference type is allowed (instanceof)  Foo<any T>.class
  13. Generic methods  Workaround for not allowing raw types to be passed when <any T> is expected  Implementation: ◦ A version of the <any T> method should be specialized ◦ Assumption: methods in a class are fixed ◦ invokedynamic is used
  14. <any T> generic method public class SpecializedMethod { public <any T> T returnValue(T value) { return value; } public static void main(String[] args) { SpecializedMethod m = new SpecializedMethod(); m.returnValue(42); } }  Bytecode at call site:
  15. Migration challenges  Wrong assumptions in some classes: T[] array = (T[]) new Object();  Problematic overloading remove(int position); remove(T element);  Incompletely generified methods remove(Object)  There’s no null value for primitives
  16. Possible approach: peeling  Implement the backward compatibility method in reference-specific layer  Add new methods in generic layer interface List<any T> { void removeByValue(T element); void removeByIndex(int pos); layer<ref T> { void remove(int pos); void remove(T element); default void removeByIndex(int pos) { remove(pos); } default void removeByValue(T t) { remove(t); } } }  The erased class will have all methods  The specialized class will only have generic layer methods
  17. Time for experiments  ArrayList or Optional class that is generic over <any T>  Write generic method over <any T> and pass: reference type, primitive and raw type  Specialized classes as method parameters, return types of methods in erased generic or non-generic classes  Usage of static member variables and static methods of specialized classes  Inner classes combination (specialized in specialized, specialized in erased, erased in specialized, specialized in non-generic)  Create new array of T inside specialized generic class  Call instanceof or .class
  18. Resources State of Specialization (by Brian Goetz) lhalla/specialization.html Stewardship the Sobering Parts Pv4yN0b0 Source, binary and behavioral compatibility ds_of_compatibility