[英]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 方法參數化的解決方案,例如
但不適用於構造函數。
這樣做的正確解決方案是什么?
使用 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.