当遇到问题时,我们该怎么做?
第1步、自己思考,并动手编写一些例子来印证自己所思;
第2步、查API文档,看看这问题中元素在API中是如何定义的。就像楼主所提的问题涉及的Class、newInstance() 方法,API中是这样描述的:“
public final class Class<T>extends Objectimplements Serializable, GenericDeclaration, Type, AnnotatedElementClass 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
以下示例使用 Class 对象来显示对象的类名:[code] void printClassName(Object obj) {
System.out.println("The class of " + obj +
" is " + obj.getClass().getName());
}[/code]”
Class类的newInstance()方法的描述:
public T newInstance()
throws InstantiationException,
IllegalAccessException创建此 Class 对象所表示的类的一个新实例。如同用一个带有一个空参数列表的 new 表达式实例化该类。如果该类尚未初始化,则初始化这个类。
注意,此方法传播 null 构造方法所抛出的任何异常,包括已检查的异常。使用此方法可以有效地绕过编译时的异常检查,而在其他情况下编译器都会执行该检查。 Constructor.newInstance 方法将该构造方法所抛出的任何异常包装在一个(已检查的)InvocationTargetException 中,从而避免了这一问题。
def runtimeClassLoader = new URLClassLoader(...)
def server = runtimeClassLoader.loadClass("org.mortbay.jetty.Server").newInstance()
...
server.start()
在Groovy中这是很容易办到的,因为start()方法是在运行时评估的,但Java需要知道编译时类型,你不能这样做:
ClassLoader runtimeClassLoader = new URLClassLoader(...)
Server server = (Server)
runtimeClassLoader.loadClass("org.mortbay.jetty.Server").newInstance()
...
server.start()
因为在第2行你会得到一个ClassCastException,服务器的声明性类型是由this.getClass().getClassLoader()加载的,但new实例是由另一个不同的类加载器加载的,不同的类加载器意味着不同的类,因此你必须使用映射调用方法和访问你需要的字段。