今天同事提出了一个问题: 将对象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的反射机制来访问给定对象的成员。