Skip to content

Instantly share code, notes, and snippets.

@arkadijs
Created April 19, 2012 09:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arkadijs/2420035 to your computer and use it in GitHub Desktop.
Save arkadijs/2420035 to your computer and use it in GitHub Desktop.
Java VM Type Erasure
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 + '}';
}
}
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 + '}';
}
}
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;
}
}
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