2014-03-28 154 views
0

我正在編寫一個將加載Java腳本的應用程序。我目前有一個GUI,它利用JFileChooser來允許用戶從他們的機器中選擇一個腳本。腳本文件可以在任何地方。它不在類路徑中。如果只有一個File對象來表示該腳本文件,我如何才能獲得它的Class表示形式?Java:動態加載外部類

我知道,要加載一個類,你需要它的二進制名稱,所以in.this.format。然而,問題在於我不知道腳本編寫者可能如何打包它。例如,他/她在開發它時可能會將腳本文件放在包foo.bar中。在我下載該腳本並將其放入我的文檔中(即而不是foo/bar中)後,我無法加載腳本而不知道它被打包在foo.bar中。如果班級名稱是Test,並且我嘗試通過執行new URLClassLoader(new URL[] { new URL(scriptFile.toURI().toURL()) })並且我做了classLoader.loadClass("Test")來創建指向腳本文件的URLClassLoader,並且我做了classLoader.loadClass("Test")我會得到一個異常,指出該班級名稱錯誤,並且正確的名稱是foo.bar.Test。但是,我該怎麼知道呢,提前?

這就是我現在所擁有的:

public class ScriptClassLoader extends URLClassLoader { 

    private final File script; 

    public ScriptClassLoader(File script) throws MalformedURLException { 
     super(new URL[] { script.toURI().toURL() }); 
     this.script = script; 
    } 

    public Class<?> load() throws ClassNotFoundException { 
     String fileName = script.getName(); 
     String className = fileName.substring(0, fileName.indexOf(".class")); 
     return loadClass(className); 
    } 
} 

人們如何加載在運行時是不是程序的類路徑的一部分腳本和類的二進制名稱是不知道?

+1

這是不意味着解決方案,但您可以捕獲拋出的異常,讀取正確的名稱,然後再次執行讀取操作。是的,這很便宜,但這是我第一次讀到你的問題時想到的第一件事。從積極的方面來看,它表明可以以正確的方式做到這一點。另外,請發佈[MCVE](http://stackoverflow.com/help/mcve)。 – user1803551

+0

我也想過這個,但覺得太便宜了。如果沒有更優雅的解決方案,我可以這樣做。 –

+0

實際上有很多解決方案,請參閱[這裏](http://stackoverflow.com/questions/11016092/how-to-load-classes-at-runtime-from-a-folder-or-jar)和[這裏] (http://stackoverflow.com/questions/20586067/how-to-load-unknown-class-from-downloaded-jar-file-during-runtime)首發。 – user1803551

回答

1

如果你只是需要從給定的.class文件加載類,不管這個班是如何命名的,你可以自己加載數據,然後調用類加載器的defineClass()方法:

RandomAccessFile raf = new RandomAccessFile(script, "r"); 
try { 
    byte[] classData = new byte[(int) raf.length()]; 
    raf.readFully(classData); 
    return super.defineClass(null, classData, 0, classData.length); 
} finally { 
    raf.close(); 
} 
+0

在這種情況下,'ScriptClassLoader'甚至不需要擴展'URLClassLoader' - 它可以直接從'ClassLoader'繼承。 – apangin

+0

如果主腳本文件引用其他腳本文件,這將如何工作?如果我在'foo.bar'中有'MainScript',並且它引用''foo.bar.other'中的'SomeOtherScriptClass',那麼如果我只加載'MainScript',該方法是否仍然有效?或者當腳本的執行達到利用'SomeOtherScriptClass'類中的方法的代碼時,我會得到一個'NoDefFoundError'? –

+1

@MartinTuskevicius爲了解析對其他類的未知引用,JVM將調用你的ClassLoader的'loadClass()'方法。你必須實現它,以便它會在'foo/bar/other'或當前目錄或你喜歡的任何地方尋找'SomeOtherScriptClass.class'。如果您沒有將.class文件放在預期的位置,那麼這就是您付出的代價。 – apangin