今天同事提出了一个问题: 将对象a 转化为类型b,b 的classpath 是在配置文件中配置的,需要在运行中使用Class.forName 动态load进来,因为之前从来没有想过类似的问题,所以懵掉了,然后迅速的查找资料,先将结果做下记录,欢迎大家来讨论一下。
想法一:
能否使用Class.forName的返回值(Class<?>)来进行类型转换,代码如下:
a o = new a();
(Class.forName("test.java.b"))o;
类型转换基本上都是在compile的时候就确定了的,所以上述代码是无法编译通过的,使用这样的方法是行不通的
想法二:
能否使用Class类中cast方法来进行类型转换?代码如下:
a o = new a();//比如a继承于b,b中存在f()方法
Class.forName("test.java.cast.b").cast(a).f();//编译不通过,找不到f方法
上述代码中,cast方法是成功的,只是转换之后的对象找不到f()方法,为什么会这样呢?下面我们看一下cast的源码
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException();
return (T) obj;
}
cast 把给定的obj 转换为泛型T,而Class.forName 的返回值为Class<?>,也就是说T是?,没有具体的类型,这样的话cast的返回值为Object
上述代码相当于
a o = new a();
Object obj = Class.forName("test.java.cast.b").cast(a);
obj.f();//出错,因为Object中没有f方法
事实证明两个想法都是行不通的,最好的办法还是放弃类型转换,使用java的反射机制来访问给定对象的成员。