Java语言中,想通过反射实例化一个抽象类的子类,问题也可以简化点,可以建个类继承这个抽象类,然后实例化子类。public abstract class MyClass<T> {
MyClass() {
}} 在代码中可以这么写:new MyClass<String>() {}但是如果通过反射,怎么把String这个type传进去,或者通过反射获得constructor,怎么把泛型信息传进去下面这个是个错误的写法,只是说明要实现的内容: new MyClass<Class.forName("String")>() {
}
MyClass() {
}} 在代码中可以这么写:new MyClass<String>() {}但是如果通过反射,怎么把String这个type传进去,或者通过反射获得constructor,怎么把泛型信息传进去下面这个是个错误的写法,只是说明要实现的内容: new MyClass<Class.forName("String")>() {
}
class MyClass<T> { private Class<T> classType; public MyClass(Class<T> classType) {
this.classType = classType;
} public T getClassType() {
try {
return classType.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
import java.lang.reflect.*;
public class Test {
static class A<T> {
T t; public void test() {
System.out.println(t);
}
} static class B<T> {
T t;
public B(T t) {this.t = t;} public void test() {System.out.println(t);}
} public static void main(String[] args) throws Throwable {
Class<?> c = A.class;
Object o = c.newInstance();
Method m = c.getDeclaredMethod("test");
m.invoke(o);
c = B.class;
Constructor con = c.getDeclaredConstructor(new Class[]{Object.class}); //用Object.class代替T
o = con.newInstance(new Object[]{"bbb"});
m = c.getDeclaredMethod("test");
m.invoke(o);
}
}
ObjectMapper mapper = new ObjectMapper();
String jackson1 = "json格式的字符串,略";
List<ClassA> list = mapper.readValue(jackson1, new TypeReference<ArrayList<ClassA>>(){});
String jackson2 = "json格式的字符串,略";
ClassB list = mapper.readValue(jackson2, new TypeReference<ClassB>(){});现在想通过反射的方式,构造TypeReference子类的实例。但是TypeReference中的_type是final并且不可访问,而且传递的类型又有可能是泛型,所以一时还没调通。各位再帮忙看看,我也再试试楼上各位的方法。package org.codehaus.jackson.type;import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;/**
* This class is used to pass full generics type information, and
* avoid problems with type erasure (that basically removes most
* usable type references from runtime Class objects).
* It is based on ideas from
* <a href="http://gafter.blogspot.com/2006/12/super-type-tokens.html"
* >http://gafter.blogspot.com/2006/12/super-type-tokens.html</a>,
* Additional idea (from a suggestion made in comments of the article)
* is to require bogus implementation of <code>Comparable</code>
* (any such generic interface would do, as long as it forces a method
* with generic type to be implemented).
* to ensure that a Type argument is indeed given.
*<p>
* Usage is by sub-classing: here is one way to instantiate reference
* to generic type <code>List<Integer></code>:
*<pre>
* TypeReference ref = new TypeReference<List<Integer>>() { };
*</pre>
* which can be passed to methods that accept TypeReference.
*/
public abstract class TypeReference<T>
implements Comparable<TypeReference<T>>
{
final Type _type; protected TypeReference()
{
Type superClass = getClass().getGenericSuperclass();
if (superClass instanceof Class<?>) { // sanity check, should never happen
throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information");
}
/* 22-Dec-2008, tatu: Not sure if this case is safe -- I suspect
* it is possible to make it fail?
* But let's deal with specifc
* case when we know an actual use case, and thereby suitable
* work arounds for valid case(s) and/or error to throw
* on invalid one(s).
*/
_type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
} public Type getType() { return _type; } /**
* The only reason we define this method (and require implementation
* of <code>Comparable</code>) is to prevent constructing a
* reference without type information.
*/
@Override
public int compareTo(TypeReference<T> o) {
// just need an implementation, not a good one... hence:
return 0;
}
}
import java.util.*;
public class Test {
static abstract class TypeReference<T> implements Comparable<TypeReference<T>> {
final Type _type; protected TypeReference() {
Type superClass = getClass().getGenericSuperclass();
if (superClass instanceof Class<?>) { // sanity check, should never happen
throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information");
}
/* 22-Dec-2008, tatu: Not sure if this case is safe -- I suspect
* it is possible to make it fail?
* But let's deal with specifc
* case when we know an actual use case, and thereby suitable
* work arounds for valid case(s) and/or error to throw
* on invalid one(s).
*/
_type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
} public Type getType() { return _type; } /**
* The only reason we define this method (and require implementation
* of <code>Comparable</code>) is to prevent constructing a
* reference without type information.
*/
@Override
public int compareTo(TypeReference<T> o) {
// just need an implementation, not a good one... hence:
return 0;
}
} public static void main(String[] args) throws Throwable {
TypeReference<ArrayList<String>> tr = new TypeReference<ArrayList<String>>() {};
System.out.println(tr.getType());
System.out.println(tr.compareTo(new TypeReference<ArrayList<String>>(){}));
}
}
List<ClassA> list = mapper.readValue(jackson1, new TypeReference<ArrayList<ClassA>>(){});是不是ArrayList<ClassA>我提前是不知道的,是通过配置文件读的,也可能是ArrayList<ClassB>等等。
抽象类是不能直接实例化的,所以你是怎么用反射实例化的?
可以通过继承抽象类的匿名类来反射生成和匿名类相同的对象
import java.util.*;
public class Test {
static abstract class TypeReference<T> implements Comparable<TypeReference<T>> {
final Type _type; protected TypeReference() {
Type superClass = getClass().getGenericSuperclass();
if (superClass instanceof Class<?>) { // sanity check, should never happen
throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information");
}
/* 22-Dec-2008, tatu: Not sure if this case is safe -- I suspect
* it is possible to make it fail?
* But let's deal with specifc
* case when we know an actual use case, and thereby suitable
* work arounds for valid case(s) and/or error to throw
* on invalid one(s).
*/
_type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
} public Type getType() { return _type; } /**
* The only reason we define this method (and require implementation
* of <code>Comparable</code>) is to prevent constructing a
* reference without type information.
*/
@Override
public int compareTo(TypeReference<T> o) {
// just need an implementation, not a good one... hence:
return 0;
}
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Throwable {
TypeReference<List<String>> tr = new TypeReference<List<String>>(){}; //先生成一个匿名类实例
Class<?> c = tr.getClass(); //取得匿名类的Class对象
Constructor con = c.getDeclaredConstructor(new Class[0]); //取得构造方法
con.setAccessible(true);
TypeReference<List<String>> o = (TypeReference<List<String>>)con.newInstance(new Object[0]); //生成和匿名类一样的对象
System.out.println(o.getType());
System.out.println(o.compareTo(tr));
}
}
static class B<T> {
T t;
public B(T t) {this.t = t;} public void test() {System.out.println(t);}
}按照这种方式构造一个T类型是ArrayList<ClassA>的B的实例,是不是要先构造一个T类型是ClassA的ArrayList实例,这样是不是嵌套了。
抽象类不能直接反射实例化的,需要继承它的子类,而你的泛型参数又是动态的,根本就没法确定这个子类,如果非要这样做,那就自己写一堆的if else来对应吧,比如
import java.util.*;
public class Test {
static abstract class TypeReference<T> implements Comparable<TypeReference<T>> {
final Type _type; protected TypeReference() {
Type superClass = getClass().getGenericSuperclass();
if (superClass instanceof Class<?>) { // sanity check, should never happen
throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information");
}
/* 22-Dec-2008, tatu: Not sure if this case is safe -- I suspect
* it is possible to make it fail?
* But let's deal with specifc
* case when we know an actual use case, and thereby suitable
* work arounds for valid case(s) and/or error to throw
* on invalid one(s).
*/
_type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
} public Type getType() { return _type; } /**
* The only reason we define this method (and require implementation
* of <code>Comparable</code>) is to prevent constructing a
* reference without type information.
*/
@Override
public int compareTo(TypeReference<T> o) {
// just need an implementation, not a good one... hence:
return 0;
}
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Throwable {
TypeReference<?> tr = null;
String className = "java.util.ArrayList<java.lang.String>"; //假设是这样的泛型参数
//String className = "java.lang.String";
List<String> cnList = new ArrayList<String>(); //解析泛型参数结果集
if (className.matches("[^<>]*?<.*?>")) { //如果包含多个泛型参数,则解析每一层参数
cnList.add(className.substring(0, className.indexOf("<")));
String sub = className.substring(className.indexOf("<")+1, className.lastIndexOf(">"));
while (sub.contains("<")) {
cnList.add(sub.substring(0, sub.indexOf("<")));
sub = sub.substring(sub.indexOf("<")+1, sub.lastIndexOf(">"));
}
cnList.add(sub);
} else {
cnList.add(className);
} if (cnList.size() == 1) {//如果只有1层泛型参数
Class<?> c = Class.forName(cnList.get(0));
if (c == String.class) { //判断是什么类型的参数,生成相应的子类对象
tr = new TypeReference<String>(){};
} else if (c == Integer.class) { //so on
tr = new TypeReference<Integer>(){};
} else {
tr = new TypeReference<Object>(){};
}
} else if (cnList.size() == 2) { //有2层泛型参数
Class<?> c1 = Class.forName(cnList.get(0));
Class<?> c2 = Class.forName(cnList.get(1));
if (List.class.isAssignableFrom(c1)) { //先判断第1层泛型参数
if (c2 == String.class) { //再判断第2层泛型参数
tr = new TypeReference<List<String>>(){}; //生成相应的子类实例
} else if (c2 == Integer.class) {
tr = new TypeReference<List<Integer>>(){};
} else {
tr = new TypeReference<List<Object>>(){};
}
} else if (Set.class.isAssignableFrom(c1)) { //so on
if (c2 == String.class) {
tr = new TypeReference<Set<String>>(){};
} else if (c2 == Integer.class) {
tr = new TypeReference<Set<Integer>>(){};
} else {
tr = new TypeReference<Set<Object>>(){};
}
} else {
tr = new TypeReference<Object>(){};
}
} else {//泛型参数太多,直接简化为用Object
tr = new TypeReference<Object>(){};
} System.out.println(tr.getType());
Class<?> c = tr.getClass(); //取得子类对象的Class对象
//use reflect to create instance //接下来就可以用c通过反射来生成实例了
TypeReference<?> o = (TypeReference<?>)c.newInstance();
System.out.println(o.getType());
}
}