Created
April 19, 2012 09:54
-
-
Save arkadijs/2420035 to your computer and use it in GitHub Desktop.
Java VM Type Erasure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package te; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class Container<T> { | |
public List<T> elems = new ArrayList<T>(); | |
public Container(T arg) { | |
this.elems.add(arg); | |
this.elems.add(arg); | |
} | |
@Override | |
public String toString() { | |
return "Container{" + "elems=" + elems + '}'; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package te; | |
import java.util.Arrays; | |
import java.util.List; | |
public class Document { | |
public List<String> items = Arrays.asList(new String[] { "apple", "bus" }); | |
public Container<String> strings = new Container<String>("many"); | |
public Container<int[]> ints = new Container<int[]>(new int[] { 42 }); | |
// Container<Integer[]> ints = new Container<>(new Integer[] { 42 }); | |
// Container<List<Integer>> ints = new Container<>(Arrays.asList(new Integer[] { 42 })); | |
// @Override | |
// public String toString() { | |
// return "Document{" + "items=" + items + '}'; | |
// } | |
@Override | |
public String toString() { | |
return "Document{" + "items=" + items + ",\n strings=" + strings + ",\n ints=" + ints + '}'; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package te; | |
import com.google.gson.Gson; | |
import com.google.gson.reflect.TypeToken; | |
import java.lang.reflect.GenericArrayType; | |
import java.lang.reflect.ParameterizedType; | |
import java.lang.reflect.Type; | |
import java.util.ArrayList; | |
import java.util.List; | |
/* 0. (slide) title | |
* switch to netbeans | |
* document | |
* document + container | |
* simplify setup -> just container | |
* string container | |
* int container | |
* print i[0] | |
* print returned structure nested types | |
* supply type via obj.getClass() | |
* int container + TypeToken | |
* supply type via TypeToken | |
* TypeToken -> ParameterizedType | |
* flashback to 1.4... | |
* list in 1.4 - list14() | |
* list in 1.5 - list15() | |
* return parameterized list + 1.7 diamond - list17returnParameterized() | |
* javap: | |
* cd ~/Work/TypeErasure | |
* javap -classpath build/classes te.Main | |
* javap -classpath build/classes te.Document | |
* 1. (slide) function & field signatures & template class _code_ does not contain parameterized type information | |
* but, inspect container element(s) -> special case, knowledge about container structure | |
* scala console | |
* cd ~/Work/TypeErasure | |
* javap -classpath build/classes te.Model | |
* scala -cp build/classes:lib/Google_Gson/gson-2.1.jar | |
* val m = new te.Model | |
* val fs = m.getClass.getDeclaredFields | |
* import collection.JavaConversions._ | |
* fs.foreach(f => println(f.getGenericType)) | |
* why it doesn't work for Container? | |
* val d = new te.Document | |
* d.getClass.getDeclaredFields.foreach(f => println(f.getGenericType)) | |
* d.ints.getClass.getDeclaredFields.foreach(f => println(f.getGenericType)) | |
* plain container | |
* val c = new te.Container[String]("try me") | |
* c.getClass.getDeclaredFields.foreach(f => println(f.getGenericType)) | |
* 2. (slide) field reflection metadata contains information about parameterizing type | |
* Field.getGenericType() | |
* 3. (slide) (anonymous) derived (template specialized) classes for which bytecode is generated, encode parameterizing type information | |
* Class.getGenericSuperclass() | |
* summary: | |
* {} | |
* cd ~/Work/TypeErasure | |
* javap -classpath build/classes te.Main\$1 | |
* javap -classpath build/classes te.Main\$2 | |
* container() | |
* containerArray() | |
* workarounds besides reflection tricks: | |
* sample data | |
* List x = new List( { "string" } ) | |
* annotation | |
* switch to intellij, open model.Person | |
* Option[Int] (Scala Int => Java int) => Option[Object] | |
* @OptionType(classOf[Int]) | |
* scalap | |
* cd ~/Work/BIS/bis/backend/services | |
* javap -classpath target/scala-2.9.1/classes model.Person | |
* scalap -classpath target/scala-2.9.1/classes model.Person | |
* TypeToken -> GenericArrayType | |
* switch to 1.6, fix <> diamond errors | |
* containerArray() | |
*/ | |
public class Main { | |
private static Gson gson = new Gson(); | |
private static int i = 0; | |
private static void p(Object o) { System.out.println(++i + ". " + o); } | |
private static void h(String h) { System.out.println("\n--- " + h.toUpperCase()); } | |
public static void main(String[] args) { | |
//gsonDocument(); | |
//gsonContainer(); | |
//gsonContainerInt(); | |
//p(list14()); | |
//p(list15()); | |
//p(list17returnParameterized()); | |
//container(); | |
containerArray(); | |
} | |
public static void gsonDocument() { | |
h("document"); | |
Document doc = new Document(); | |
p(doc); | |
String docJson = gson.toJson(doc); | |
p(docJson); | |
Document docFromJson = gson.fromJson(docJson, Document.class); | |
p(docFromJson); | |
} | |
public static void gsonContainer() { | |
h("string container"); | |
Container<String> stringContainer = new Container<String>("alone"); | |
p(stringContainer); | |
String stringContainerJson = gson.toJson(stringContainer); | |
p(stringContainerJson); | |
Container<String> stringContainerFromJson = gson.fromJson(stringContainerJson, Container.class); | |
p(stringContainerFromJson); | |
} | |
public static void gsonContainerInt() { | |
h("int array container"); | |
Container<int[]> intArrayContainer = new Container<int[]>(new int[] { 42 }); | |
p(intArrayContainer); | |
// Container<List<Integer>> intArrayContainer = new Container<List<Integer>>(Arrays.asList(new Integer[] { 42 })); | |
String intArrayContainerJson = gson.toJson(intArrayContainer); | |
p(intArrayContainerJson); | |
h("int array container from json"); | |
// Container<int[]> intArrayContainerFromJson = gson.fromJson(intArrayContainerJson, | |
// Container.class); | |
// Container<int[]> intArrayContainerFromJson = gson.fromJson(intArrayContainerJson, | |
// intArrayContainer.getClass()); | |
Container<int[]> intArrayContainerFromJson = gson.fromJson(intArrayContainerJson, | |
new TypeToken<Container<int[]>>(){}.getType()); | |
// p(intArrayContainerFromJson); | |
int[] i = intArrayContainerFromJson.elems.get(0); | |
p(i[0]); | |
p(intArrayContainerFromJson.elems); | |
p(intArrayContainerFromJson.elems.get(0)); | |
Object o = intArrayContainerFromJson.elems.get(0); | |
p(o.getClass().getName()); | |
Object n; | |
if (o instanceof List) | |
n = ((List) o).get(0); | |
else | |
n = ((int[]) o)[0]; | |
p(n.getClass().getName()); | |
} | |
public static List list14() { | |
List l = new ArrayList(); | |
l.add("j"); | |
l.add(new Integer(10)); | |
Integer i = (Integer) l.get(1); | |
String s = (String) l.get(0); | |
return l; | |
} | |
public static List<String> list15() { | |
List<String> l = new ArrayList<String>(); | |
l.add("j"); | |
// l.add(new Integer(10)); | |
String s = l.get(0); | |
return l; | |
} | |
public static List<String> list17returnParameterized() { | |
List<String> l = new ArrayList<String>(); | |
l.add("j"); | |
String s = l.get(0); | |
return l; | |
} | |
public static Container container() { | |
Container<String> c = new Container<String>("j") {}; | |
Type t = c.getClass().getGenericSuperclass(); | |
if (t instanceof ParameterizedType) { | |
ParameterizedType p = (ParameterizedType) t; | |
Type r = p.getActualTypeArguments()[0]; | |
p(r); | |
p(r.getClass().getName()); | |
} | |
return c; | |
} | |
public static Container containerArray() { | |
Container<int[]> c = new Container<int[]>(new int[] { 42 }) {}; | |
Type t = c.getClass().getGenericSuperclass(); | |
if (t instanceof ParameterizedType) { | |
ParameterizedType p = (ParameterizedType) t; | |
Type r = p.getActualTypeArguments()[0]; | |
p(r); | |
p(r.getClass().getName()); | |
if (r instanceof GenericArrayType) { | |
GenericArrayType g = (GenericArrayType) r; | |
p(g.getGenericComponentType()); | |
p(g.getGenericComponentType().getClass().getName()); | |
} | |
} | |
return c; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package te; | |
import java.util.List; | |
public class Model { | |
List<String> lstr; | |
List<Integer> lint; | |
List<int[]> larr; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment