2015-10-15 34 views
0

有一個例子:如何加載不同的類(定義),而不是要求一個,保持相同的名稱

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); 
    } 

} 

我嘗試了上面的代碼,但它並沒有爲我工作。拋出異常:
線程「main」中的異常java.lang.ClassNotFoundException:bar/Bar

類定義是否包含類的名稱?在裝載過程中是否有任何方法可以改變它?

UPDATE

我已經找到一種方法來修改類名稱中使用了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()它仍然打印 「欄:bar.Bar」 的時候。
我想我已經錯過了一些代碼,所以存在兩個具有相同名稱的類(原始的和baz.Baz的重命名副本)。

+0

嘗試刪除程序包名稱。而不是bar.Bar,只是Bar而不是baz.Baz,就是Baz。讓我知道它是否有效。你還確定Bar/Baz是classpath的一部分嗎? –

回答

0

按我的理解,因爲你是在這種情況下,做你不能改變的類名。 Class.forName()驗證你從你請求的類中加載的類並失敗。你可以直接使用你定義的類加載器加載你的類。

+0

有什麼例子嗎? – Victor

+0

你的情況,你可以使用類 clazz中=新MimicClassLoader( Thread.currentThread()getContextClassLoader())的loadClass( 「bar.Bar」)。 –

相關問題