2013-08-22 37 views
0

我有一個新的小Swing項目,我需要從兩個不同的罐子中加載同一個類,這些罐子是第三方,所以我沒有源代碼。從不同罐子中加載同一個類

例如我需要從兩個罐子中加載myClass。 jar1.jar jar2.jar

只是我什麼,我需要做的:

public void doMyClassLogicVersion1() { 

    Loader = // here i need to load jar1.myClass. 
    // myClass need a two params to initialize it in the normal case 
    // also i need to access its static members 
    // do the logic of myClass version1 

} 

public void doMyClassLogicVersion2() { 

    Loader = // here i need to load jar2.myClass. 
    // myClass need a two params to initialize it in the normal case 
    // also i need to access its static members 
    // do the logic of myClass version2 
} 

這樣我可以做到這一點,我知道這是不好,但我真的需要。

回答

2

您可以加載新的代碼轉換成新的類加載器相對容易:

案例1:如果你的類在當前的背景下,通用父接口(或類),例如Runnable接口,您可以使用此代碼:

public void doMyClassLogicVersion1() { 
    ClassLoader loader = URLClassLoader.newInstance(
    new URL[] { yourURL1 }, 
    getClass().getClassLoader() 
    ); 
    Class<?> clazz = Class.forName("mypackage.MyClass", true, loader); 
    Class<? extends Runnable> runClass = clazz.asSubclass(Runnable.class); 
    // Avoid Class.newInstance, for it is evil. 
    Constructor<? extends Runnable> ctor = runClass.getConstructor(); 
    Runnable doRun = ctor.newInstance(); 
    doRun.run(); 
} 

public void doMyClassLogicVersion2() { 
    ClassLoader loader = URLClassLoader.newInstance(
    new URL[] { yourURL2 }, 
    getClass().getClassLoader() 
    ); 
    Class<?> clazz = Class.forName("mypackage.MyClass", true, loader); 
    Class<? extends Runnable> runClass = clazz.asSubclass(Runnable.class); 
    // Avoid Class.newInstance, for it is evil. 
    Constructor<? extends Runnable> ctor = runClass.getConstructor(); 
    Runnable doRun = ctor.newInstance(); 
    doRun.run(); 
} 

案例2:如果類並不共享共同的父:

public void doMyClassLogicVersion1() { 
    ClassLoader loader = URLClassLoader.newInstance(
    new URL[] { yourURL1 }, 
    getClass().getClassLoader() 
    ); 
    Class<?> clazz = Class.forName("mypackage.MyClass", true, loader); 
    // Avoid Class.newInstance, for it is evil. 
    Constructor<?> ctor = runClass.getConstructor(); 
    Object obj = ctor.newInstance(); 

    String methodName = "getName"; 

    java.lang.reflect.Method method; 
    try { 
     method = clazz.getMethod(methodName, param1.class, param2.class, ..); 
    } catch (SecurityException e) { 
     // ... 
    } catch (NoSuchMethodException e) { 
     // ... 
    } 

    try { 
     method.invoke(obj, arg1, arg2,...); 
    } catch (IllegalArgumentException e) { 
     // ... 
    } catch (IllegalAccessException e) { 
     // ... 
    } catch (InvocationTargetException e) { 
     // ... 
    } 
} 

public void doMyClassLogicVersion2() { 
    ClassLoader loader = URLClassLoader.newInstance(
    new URL[] { yourURL2 }, 
    getClass().getClassLoader() 
    ); 
    Class<?> clazz = Class.forName("mypackage.MyClass", true, loader); 
    // Avoid Class.newInstance, for it is evil. 
    Constructor<?> ctor = runClass.getConstructor(); 
    Object obj = ctor.newInstance(); 

    String methodName = "getName"; 

    java.lang.reflect.Method method; 
    try { 
     method = clazz.getMethod(methodName, param1.class, param2.class, ..); 
    } catch (SecurityException e) { 
     // ... 
    } catch (NoSuchMethodException e) { 
     // ... 
    } 

    try { 
     method.invoke(obj, arg1, arg2,...); 
    } catch (IllegalArgumentException e) { 
     // ... 
    } catch (IllegalAccessException e) { 
     // ... 
    } catch (InvocationTargetException e) { 
     // ... 
    } 
} 
+0

答到刪除的問題:爲什麼URLClassLoader.newInstance? URLClassLoader.newInstance爲指定的URL和默認的父類加載器創建一個新的URLClassLoader實例。如果安裝了安全管理器,則此方法返回的URLClassLoader的loadClass方法將在加載該類之前調用​​SecurityManager.checkPackageAccess。 來源:http://download.java.net/jdk8/docs/api/java/net/URLClassLoader.html#newInstance%28java.net.URL[]%29 –

+0

謝謝mohammad,但我仍然需要調用特定方法包含加載的類。所以這將與你的代碼來。並且myClass構造函數顯示包含兩個pat。 – Salah

+0

這兩個類是否有相同的父類?如果他們有,那麼你可以用我的代碼中的Runnable替換那個父類。 –

0

是的,你可以做到。爲避免出現問題,我建議您不要將任何jar放在常規CLASSPATH中,創建2個不同的線程,並在啓動它們之前將每個線程的ContextClassLoader設置爲相應的jar。

相關問題