簡體   English   中英

使用反射Java的`newInstance`實例化Scala類

[英]instantiating a Scala class using reflection Java's `newInstance`

對於某些特殊用例,我有一個小的實用程序,可以使用動態類加載器DynamicClassLoader從jar中加載Java類。 這對於jars中包含的Java類很好用。 從jar加載Scala類也可以正常工作。 但是,實例化已加載的Scala類會導致以下異常。 看起來Scala類具有私有的默認構造函數? 請注意,已編譯的Scala類名稱以$結尾

java.lang.IllegalAccessException: Class XXX can not access a member of class ScalaClassYYY$ with modifiers "private"

下面的代碼段說明了我要實現的目標的思想,並提供了更多背景信息。 異常發生在帶注釋的行:

// deploy and register the new code
byte[] jarBytes = (byte[]) ((Object) message.getAttachment("jar"));
String registerClassName = message.getAttachment("register");
logger.debug("the register is '" + registerClassName + "'");

DynamicClassLoader loader = new DynamicClassLoader(jarBytes);
Class<?> registerClass = loader.lookUp(registerClassName);
// ===> this is where the java.lang.IllegalAccessException happens 
IRegisterExecutor registerExecutor = (IRegisterExecutor) registerClass.newInstance();
registerExecutor.register();

任何想法如何解決?

顯然,您需要將默認構造函數設為公共(沒有公共默認構造函數的Java類也無法使用)。 例如

class ScalaClassYYY() {
  ...
}

或者如果您希望主要構造函數接受一些參數,

class ScalaClassYYY(arg1: Int) {
  def this() = this(0)
}

但是從

請注意,已編譯的Scala類名稱以$結尾

看來您實際上是在嘗試實例化Scala object

object ScalaClassYYY { ... }

在這種情況下,您不應創建新實例,而應使用現有實例:

(IRegisterExecutor) registerClass.getField("MODULE$").get(null);

編輯:

我沒有在您的答案中看到如何將默認的公共構造函數添加到不需要任何參數的Scala類中。

不需要任何參數的class不是 object )已經具有默認的公共構造函數(我的第一個示例)。

實際上,在Java中,默認情況下所有類都提供一個公共默認構造函數

不。僅那些沒有構造函數且帶有參數的類。

刪除“((如果沒有公共默認構造函數,它也將不適用於Java類)”,因為它是錯誤的

Class.newInstance()文檔

IllegalAccessException如果該類或其無效構造函數不可訪問。

所以我很確定這是正確的。 如果它確實適用於沒有公共默認構造函數的Java類,則這似乎是您使用的類加載器中的主要錯誤。 您可以使用如下所示的Java類對其進行測試:

public class TestClass implements IRegisterExecutor {
    public TestClass(int dummy) {}

    // some implementation for IRegisterExecutor methods to get it to compile
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM