簡體   English   中英

如何在使用 class 參數化的 java 中創建構造函數?

[英]How to create constructor in java parameterized with class?

我想要一個 class 來運行 java 中的其他類,例如使用 class 參數化的構造函數,以便稍后在類似於此的 ZA2F2ED24F8EBC2CBB4 上運行 ZA2F2ED24F8EBC2CBB4

class MyClass{
    Class classToRun;
    public MyClass(Class c) {
        super();
        this.classToRun = c;
    }
    public void runClass(){
        classToRun.someStaticMethod();
    }
}

其中classToRun可能的類沒有共同的祖先,但都有方法someStaticMethod ,並且不知道運行它們的 MyClass。

但是有問題,比如內部類不能有 static 方法,類不能轉換 Class 等。

有使用 class 方法參數化的解決方案,例如

如何在 Java 中將 class 作為參數傳遞?

將 class 作為參數傳遞給 java 中的方法

但不適用於構造函數。

這樣做的正確解決方案是什么?

使用 lambda 並傳遞方法引用:它們在方法簽名上匹配。 對於void someStaticMethod()您可以使用Runnable

class MyClass{
    private final Runnable methodToRun;
    public MyClass(Runnable someStaticMethod) {
        methodToRun = someStaticMethod;
    }
    public void runClass(){
        methodToRun.run();
    }
}

new MyClass(SomeClass::someStaticMethod).runClass();

您不能強制傳遞的方法具有正確的名稱,但看起來更整潔恕我直言。

您需要了解generics是什么。

界面

public interface SomeInterface {
    void someStaticMethod();
}

利用

class MyClass<T extends SomeInterface>{
    T classToRun;
    public MyClass(T c) {
        super();
        this.classToRun = c;
    }
    public void runClass(){
        classToRun.someStaticMethod();
    }
}

如果要在只有Class實例時執行方法,則必須使用反射。

在下面的代碼中, runClass使用它的名稱作為String找到 class 的方法,然后執行它。 此代碼假定方法是 static,同樣忽略任何異常處理。

以下代碼打印"test"

class MyClass {
    Class classToRun;
    public MyClass(Class c) {
        this.classToRun = c;
    }
    public void runClass() throws Exception {
        Optional<Method> method = Arrays.stream(classToRun.getDeclaredMethods()).filter(m -> m.getName().equals("someStaticMethod")).findFirst();
        if(!method.isPresent()) {
            throw new RuntimeException();
        }
        method.get().invoke(null);
    }
}


class Main {
    public static void main(String[] args) throws Exception {
        MyClass mc = new MyClass(Main.class);
        mc.runClass();
    }

    static void someStaticMethod() {
        System.out.println("test");
    }
}

由於 3 個答案中有 2 個不重要,因此我決定發布兩個答案的固定版本,只要它們可以修復。

上面的f1sh版本應如下所示:

public class ClassToRunOthers {
    Class classToRun;
    public ClassToRunOthers(Class c) {
        this.classToRun = c;
    }
    public void runClass() throws Exception {
        Optional<Method> method = Arrays.stream(classToRun.getDeclaredMethods()).filter(m -> m.getName().equals("someStaticMethod")).findFirst();
        if(!method.isPresent()) {
            throw new RuntimeException();
        }
        method.get().invoke(null);
    }
    public static void main(String[] args) throws Exception {
        ClassToRunOthers mc = new ClassToRunOthers(SomeClass.class);
        mc.runClass();
    }
}

class SomeClass {
    static void someStaticMethod() {
        System.out.println("test");
    }
}

上面的zwei解決方案無法在沒有反射的情況下修復,因為 generics 不是重點。 Evan 如果您嘗試不使用SomeInerface進行參數化(因為SomeClass不擴展常見的SomeInterface ),而是使用 Object,它仍然無法解決問題:

public class MyClass<T extends Object> {
    T classToRun;

    public MyClass(T c) {
        super();
        this.classToRun = c;
    }

    public void runClass() {
        //        classToRun.someStaticMethod(); // Cannot resolve method 'someStaticMethod' in 'T'
    }

    public static void main(String[] args) {
        MyClass mc = new MyClass(SomeClass.class);
    }
}

class SomeClass {
    static void someStaticMethod() {
        System.out.println("test");
    }
}

這可以像上面一樣通過反射來修復。 我相信,它可以通過注釋以某種優雅的方式完成,並且可能有人會與我們分享這樣的解決方案,或者我會在時間允許的情況下自己做。 現在對我自己來說,在提出問題后的第二天,在構造函數中的字符串中保存 class 名稱的解決方案可以解決問題。

暫無
暫無

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

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