diff --git a/lang/pom.xml b/lang/pom.xml
index 1fa88c0..f52cbd7 100644
--- a/lang/pom.xml
+++ b/lang/pom.xml
@@ -9,7 +9,7 @@
4.0.0
- core
+ lang
junit
diff --git a/pom.xml b/pom.xml
index 4b17a1e..80892d1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
reflection
gui
async
- core
+ lang
diff --git a/reflection/src/main/java/fr/gasser/reflection/dynamicload/DynamicLoadDemo.java b/reflection/src/main/java/fr/gasser/reflection/DynamicLoadDemo.java
similarity index 95%
rename from reflection/src/main/java/fr/gasser/reflection/dynamicload/DynamicLoadDemo.java
rename to reflection/src/main/java/fr/gasser/reflection/DynamicLoadDemo.java
index 4126841..eaa4a18 100644
--- a/reflection/src/main/java/fr/gasser/reflection/dynamicload/DynamicLoadDemo.java
+++ b/reflection/src/main/java/fr/gasser/reflection/DynamicLoadDemo.java
@@ -1,4 +1,4 @@
-package fr.gasser.reflection.dynamicload;
+package fr.gasser.reflection;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
@@ -18,7 +18,7 @@ public class DynamicLoadDemo {
*/
private static final String SOURCE =
"package test;"
- + "import static fr.gasser.reflection.dynamicload.DynamicLoadDemo.*;"
+ + "import static DynamicLoadDemo.*;"
+ "public class Test implements IDynamicLoad {"
+ " static { System.out.println(\"Test\"); }"
+ " @Override public String doSomething() {"
diff --git a/reflection/src/main/java/fr/gasser/reflection/GenericClass.java b/reflection/src/main/java/fr/gasser/reflection/GenericClass.java
new file mode 100644
index 0000000..8ea9901
--- /dev/null
+++ b/reflection/src/main/java/fr/gasser/reflection/GenericClass.java
@@ -0,0 +1,26 @@
+package fr.gasser.reflection;
+
+import java.lang.reflect.ParameterizedType;
+
+/**
+ * Shows how to access generic type parameter type at runtime.
+ */
+public abstract class GenericClass {
+
+ private Class clazz;
+
+ @SuppressWarnings("unchecked")
+ private GenericClass() {
+ ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
+ this.clazz = (Class) genericSuperclass.getActualTypeArguments()[0];
+ }
+
+ Class getClazz() {
+ return clazz;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(new GenericClass() {}.getClazz());
+ System.out.println(new GenericClass() {}.getClazz());
+ }
+}
diff --git a/reflection/src/main/java/fr/gasser/reflection/GenericsTest.java b/reflection/src/main/java/fr/gasser/reflection/GenericsTest.java
new file mode 100644
index 0000000..64aaf03
--- /dev/null
+++ b/reflection/src/main/java/fr/gasser/reflection/GenericsTest.java
@@ -0,0 +1,26 @@
+package fr.gasser.reflection;
+
+public class GenericsTest {
+
+ private TypeToken typeToken;
+ private T data;
+
+
+ public GenericsTest(T data) {
+ this.data = data;
+ this.typeToken = new TypeToken() {};
+ }
+
+ @Override
+ public String toString() {
+ return "GenericsTest{" +
+ "type=" + typeToken.type +
+ ", data=" + data +
+ '}';
+ }
+
+ public static void main(String[] args) {
+ GenericsTest g = new GenericsTest<>(5L);
+ System.out.println(g);
+ }
+}
diff --git a/reflection/src/main/java/fr/gasser/reflection/TypeToken.java b/reflection/src/main/java/fr/gasser/reflection/TypeToken.java
new file mode 100644
index 0000000..59a3121
--- /dev/null
+++ b/reflection/src/main/java/fr/gasser/reflection/TypeToken.java
@@ -0,0 +1,102 @@
+package fr.gasser.reflection;
+
+import java.lang.reflect.*;
+import java.util.List;
+
+/*
+ * {@code TypeToken> list = new TypeToken>() {};}
+ */
+public class TypeToken {
+ private final Class super T> rawType;
+ final Type type;
+ private final int hashCode;
+
+ @SuppressWarnings("unchecked")
+ TypeToken() {
+ this.type = getSuperclassTypeParameter(getClass());
+ this.rawType = (Class super T>) getRawType(type);
+ this.hashCode = type.hashCode();
+ }
+
+
+ /**
+ * Unsafe. Constructs a type literal manually.
+ */
+ @SuppressWarnings("unchecked")
+ private TypeToken(Type type) {
+ this.type = checkNotNull(type);
+ this.rawType = (Class super T>) getRawType(this.type);
+ this.hashCode = this.type.hashCode();
+ }
+
+ /**
+ * Returns the type from super class's type parameter
+ */
+ private static Type getSuperclassTypeParameter(Class> subclass) {
+ Type superclass = subclass.getGenericSuperclass();
+ if (superclass instanceof Class) {
+ throw new RuntimeException("Missing type parameter.");
+ }
+ ParameterizedType parameterized = (ParameterizedType) superclass;
+ return parameterized.getActualTypeArguments()[0];
+ }
+
+ public static Class> getRawType(Type type) {
+ if (type instanceof Class>) {
+ // type is a normal class.
+ return (Class>) type;
+
+ } else if (type instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType) type;
+
+ // I'm not exactly sure why getRawType() returns Type instead of Class.
+ // Neal isn't either but suspects some pathological case related
+ // to nested classes exists.
+ Type rawType = parameterizedType.getRawType();
+ checkArgument(rawType instanceof Class);
+ return (Class>) rawType;
+
+ } else if (type instanceof GenericArrayType) {
+ Type componentType = ((GenericArrayType)type).getGenericComponentType();
+ return Array.newInstance(getRawType(componentType), 0).getClass();
+
+ } else if (type instanceof TypeVariable) {
+ // we could use the variable's bounds, but that won't work if there are multiple.
+ // having a raw type that's more general than necessary is okay
+ return Object.class;
+
+ } else if (type instanceof WildcardType) {
+ return getRawType(((WildcardType) type).getUpperBounds()[0]);
+
+ } else {
+ String className = type == null ? "null" : type.getClass().getName();
+ throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
+ + "GenericArrayType, but <" + type + "> is of type " + className);
+ }
+ }
+
+ private static void checkArgument(boolean condition) {
+ if (!condition) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private static T checkNotNull(T obj) {
+ if (obj == null) {
+ throw new NullPointerException();
+ }
+ return obj;
+ }
+
+ /**
+ * Gets type literal for the given {@code Class} instance.
+ */
+ public static TypeToken get(Class type) {
+ return new TypeToken(type);
+ }
+
+ public static void main(String[] args) {
+ TypeToken> token = new TypeToken>() {};
+ System.out.println(token);
+ }
+}