簡體   English   中英

如何正確使用類類型的參數?

[英]How to properly use a parameter of type class?

在java中,我想做這樣的事情

    public class Tata{ 

        public static void f(){
            //something
        }
        public static void g(){
            //something
        }
    }

    public class Titi{ 

        public static void f(){
            //something
        }
        public static void g(){
            //something
        }
    }

    public class Toto{

        private Class c = Tata.class; //or Titi.class 

        public static void main(String[] args) {
            c.f();
            c.g();
        }
    }

准確地說,我希望能夠在TataTiti類之間自由切換,使用它們各自的方法fg

這不能按預期工作,因為我收到了無法解析方法 'f()' 的錯誤。 簡單地替換cf(); cg(); Tata.f(); Tata.g(); 工作正常,但違背了使用參數的目的。 如何解決這個問題?

畢竟將評論變成答案..處理您想要的正確(Java)方法是使用接口。 因此,在您的演示代碼中,實現如下:

public interface TheFGFunctions {
    void f();
    void g();
}
public class Tata implements TheFGFunctions {
    @Override
    public void f() {
        //something
    }
    @Override
    public void g() {
        //something
    }
}
public class Titi implements TheFGFunctions {
    @Override
    public void f() {
        //something
    }
    @Override
    public void g() {
        //something
    }
}
public class Toto {
    private TheFGFunctions c;
    public Toto(TheFGFunctions c) {
        this.c = c;
    }
    public void notStaticFunction() {
        c.f();
        c.g();
    }
}

這種方式是完全類型安全的,處理零異常!

您可以使用反射:

private Class c = Tata.class;

public Toto() throws Exception {
    c.getMethod("f").invoke(null);
    c.getMethod("g").invoke(null);
}

這是我的塔塔課

public class Tata {
    public static void f() {
        System.out.println("ffff");
    }

    public static void g() {
        System.out.println("gggg");
    }
}

new Toto()調用的輸出:

ffff
gggg

更新(帶參數調用):

public Toto() throws Exception {
    c.getMethod("f", String.class).invoke(null, "paramValue1");
    c.getMethod("g", String.class).invoke(null, "paramValue2");
}

public class Tata {
    public static void f(String param1) {
        System.out.println("ffff " + param1);
    }

    public static void g(String param2) {
        System.out.println("gggg " + param2);
    }
}

輸出:

ffff paramValue1
gggg paramValue2

不能以多態方式訪問靜態方法。 Java 語言不支持它。

您當前的方法失敗的原因是c是類Class的實例,而類Class沒有定義方法f()g()

(它定義的方法列在Classjavadoc中。請注意Classfinal因此您不能使用額外的方法創建自定義子類。)


簡單的替代方法是使用反射; 例如

     Class c = 
     Method f = c.getMethod("f");
     f.invoke(null);   // because it is static

但請注意:

  • 這不是靜態類型安全的。 編譯器無法判斷您何時嘗試在沒有此類方法的類上使用靜態f()的錯誤。

  • 您需要處理一些例外情況; 例如,缺少方法、不正確的簽名、非靜態方法、沒有正確訪問權限的方法。


其他答案建議創建一個接口和包裝類,以使某些靜態方法可調度。 它將工作並且它將是編譯時類型安全的(!)但是有很多樣板代碼要編寫。


@Michael Michailidis 評論道:

因此接口!

是的......有點。 您只能對接口上聲明的實例方法進行多態分派。 這意味着您必須擁有TataTiti的實例,並在其上調用方法。 我對問題的閱讀是作者想要避免這種情況。

(IMO,避免才是真正的問題。你最好不要試圖避免實例方法。)

FWIW,您可以在接口中聲明靜態方法(自 Java 8 起),但它們的行為與您在類中聲明它們的行為相同。 你將無法派遣...

編寫包裝接口

interface CWrapper {
    void f();
    void g();
}

和包含方法的每個類的包裝類工廠方法

class CWrappers {
    CWrapper forTiti(Class<Titi> titiClass) {
        return new CWrapper() {
            void f() { Titi.f(); }
            void g() { Titi.g(); }
        }
    }
    // another factory method for Tata
}

然后你可以使用它:

public class Toto {
    private CWrapper c = CWrappers.forTata(Tata.class); //or forTiti(Titi.class)

    public static void main(String[] args) {
        c.f();
        c.g();
    }
}

暫無
暫無

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

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