Top Banner
Primitives in Generics current state Ivan St. Ivanov
18

Primitives in Generics

Jul 17, 2015

Download

Technology

Ivan Ivanov
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Primitives in Generics

Primitives in Genericscurrent state

Ivan St. Ivanov

Page 2: Primitives in Generics

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

Page 3: Primitives in Generics

The state of generics

Only over reference types

If you want List<int>:List<Integer> intList = new ArrayList<>();

Performance penalty:Heade

rPointer

Pointer

Pointer

Pointer

Heade

rint Heade

rint Heade

rint Heade

rint

Page 4: Primitives in Generics

But why?

Type erasure in genericspublic 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

Page 5: Primitives in Generics

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!

Page 6: Primitives in Generics

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

Page 7: Primitives in Generics

Proposed syntax

Introduce any type variable modifierpublic 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);

Page 8: Primitives in Generics

What about byte code?

ErasedBox (for reference types)

SpecialBox (for primitive types)

Page 9: Primitives in Generics

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

Page 10: Primitives in Generics

Representation in bytecode

Erasure of reference types,

specialization for primitives

Look again at SpecialBox usage site:

Class name augmented with

specialization info

Page 11: Primitives in Generics

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

Page 12: Primitives in Generics

Available only for <any T>

Support for new T[size]

Use it where reference type is allowed

(instanceof)

Foo<any T>.class

Page 13: Primitives in Generics

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

Page 14: Primitives in Generics

<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:

Page 15: Primitives in Generics

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

Page 16: Primitives in Generics

Possible approach: peeling Implement the backward compatibility method in

reference-specific layer

Add new methods in generic layerinterface 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

Page 17: Primitives in Generics

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

Page 18: Primitives in Generics

Resources

State of Specialization (by Brian Goetz)

http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html

Stewardship the Sobering Parts

https://www.youtube.com/watch?v=2y5Pv4yN0b0

Source, binary and behavioral compatibility

https://blogs.oracle.com/darcy/entry/kinds_of_compatibility