[英]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();
}
}
准確地說,我希望能夠在Tata和Titi類之間自由切換,使用它們各自的方法f或g 。
這不能按預期工作,因為我收到了無法解析方法 '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()
。
(它定義的方法列在Class
的javadoc中。請注意Class
是final
因此您不能使用額外的方法創建自定義子類。)
簡單的替代方法是使用反射; 例如
Class c =
Method f = c.getMethod("f");
f.invoke(null); // because it is static
但請注意:
這不是靜態類型安全的。 編譯器無法判斷您何時嘗試在沒有此類方法的類上使用靜態f()
的錯誤。
您需要處理一些例外情況; 例如,缺少方法、不正確的簽名、非靜態方法、沒有正確訪問權限的方法。
其他答案建議創建一個接口和包裝類,以使某些靜態方法可調度。 它將工作並且它將是編譯時類型安全的(!)但是有很多樣板代碼要編寫。
@Michael Michailidis 評論道:
因此接口!
是的......有點。 您只能對接口上聲明的實例方法進行多態分派。 這意味着您必須擁有Tata
或Titi
的實例,並在其上調用方法。 我對問題的閱讀是作者想要避免這種情況。
(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.