如何加载不同的类(定义)而不是请求的类,保持相同的名称

时间:2015-10-15 09:28:57

标签: java class classloader

有一个例子:

package bar;

public class Bar {

    public void doSomething() {
        System.out.println("Bar: " + getClass().getName());
    }

}


package baz;

public class Baz {

    public void doSomething() { // note the same signature
        System.out.println("Baz: "  + getClass().getName());
    }

}


package foo;

public class Foo {

    public static void main(String[] args) throws ClassNotFoundException {
        Class.forName("bar.Bar", false, new MimicClassLoader(
                Thread.currentThread().getContextClassLoader()));
        // must print "Baz: bar.Bar"
        new bar.Bar().doSomething();
    }

}


package foo;

public class MimicClassLoader extends ClassLoader {

    public MimicClassLoader(ClassLoader parent) {
        super(parent);
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        if ("bar.Bar".equals(name)) {
            name = "baz.Baz";
        }
        return super.loadClass(name);
    }

}

我尝试了上面的代码,但它对我不起作用。抛出异常:
线程&#34; main&#34;中的例外情况java.lang.ClassNotFoundException:bar / Bar

类定义是否包含类的名称?在加载过程中有没有办法改变它?

更新

我找到了一种使用Javassist库修改类名的方法:

public class MimicClassLoader extends ClassLoader {

    public MimicClassLoader(ClassLoader parent) {
        super(parent);
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        if ("bar.Bar".equals(name)) {
            byte[] bytes;
            try {
                bytes = javassist.ClassPool.getDefault()
                        .getAndRename("baz.Baz", "bar.Bar").toBytecode();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            Class<?> clazz = defineClass(name, bytes, 0, bytes.length);
            // prints "Baz: bar.Bar"
            // clazz.getMethod("doSomething").invoke(clazz.newInstance());
            return clazz;
        }
        return getParent().loadClass(name);
    }

}

但是当使用new Bar().doSomething()时,它仍会打印&#34; Bar:bar.Bar&#34;。
我想我已经错过了一些代码,因此存在两个具有相同名称的类(原始类和重命名的baz.Baz副本)。

1 个答案:

答案 0 :(得分:0)

根据我的理解,您不能像在这种情况下那样更改类名。 Class.forName()从您请求的那个验证您加载的类并失败。您可以使用您定义的类加载器直接加载您的类。