简体   繁体   English

如何正确使用类类型的参数?

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

In java, I'd like to do something like this在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();
        }
    }

To be precise, I'd like to be able to freely switch between classes Tata and Titi , to use their respective methods f or g .准确地说,我希望能够在TataTiti类之间自由切换,使用它们各自的方法fg

This doesn't work as intended, as I get the cannot resolve method 'f()' error.这不能按预期工作,因为我收到了无法解析方法 'f()' 的错误。 Simply replacing cf();简单地替换cf(); and cg();cg(); with Tata.f();Tata.f(); and Tata.g();Tata.g(); works fine, but defeats the purpose of using a parameter.工作正常,但违背了使用参数的目的。 How to solve this?如何解决这个问题?

Will turn the comment into answer after all.. The correct (Java) way to deal with what you want is the use of interface.毕竟将评论变成答案..处理您想要的正确(Java)方法是使用接口。 So in your demo code the implementation would be the following:因此,在您的演示代码中,实现如下:

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();
    }
}

This way is totally typesafe with zero exceptions to deal with!这种方式是完全类型安全的,处理零异常!

You could use reflections:您可以使用反射:

private Class c = Tata.class;

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

Here my Tata class这是我的塔塔课

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

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

Output on new Toto() call: new Toto()调用的输出:

ffff
gggg

Update (call with parameters):更新(带参数调用):

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);
    }
}

Output:输出:

ffff paramValue1
gggg paramValue2

You cannot access a static method polymorphically.不能以多态方式访问静态方法。 The Java language doesn't support it. Java 语言不支持它。

The reason your current approach fails is that c is an instance of the class Class , and the class Class doesn't define methods f() or g() .您当前的方法失败的原因是c是类Class的实例,而类Class没有定义方法f()g()

(The methods that it does define are listed in the javadoc for Class . Note that Class is final so you can't create a custom subclass with extra methods.) (它定义的方法列在Classjavadoc中。请注意Classfinal因此您不能使用额外的方法创建自定义子类。)


The simple alternative is to use reflection;简单的替代方法是使用反射; eg例如

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

But note:但请注意:

  • This is not statically type-safe.这不是静态类型安全的。 The compiler cannot tell when you make the mistake of trying to use a static f() on a class that doesn't have such a method.编译器无法判断您何时尝试在没有此类方法的类上使用静态f()的错误。

  • There are a few exceptions that you need to deal with;您需要处理一些例外情况; eg missing methods, incorrect signatures, methods that are not static, methods that don't have the correct access.例如,缺少方法、不正确的签名、非静态方法、没有正确访问权限的方法。


Other answers have proposed creating an interface and wrapper classes to make certain static methods dispatchable.其他答案建议创建一个接口和包装类,以使某些静态方法可调度。 It will work and it will be compile-time type-safe (!) but there is a lot of boiler plate code to write.它将工作并且它将是编译时类型安全的(!)但是有很多样板代码要编写。


@Michael Michailidis commented: @Michael Michailidis 评论道:

Thus interfaces!因此接口!

Yea ... kind of.是的......有点。 You can only dispatch polymorphically on instance methods declared on an interface.您只能对接口上声明的实例方法进行多态分派。 That implies that you must have an instance of Tata or Titi , and call the methods on it.这意味着您必须拥有TataTiti的实例,并在其上调用方法。 My reading of the Question is that the author wants to avoid that.我对问题的阅读是作者想要避免这种情况。

(IMO, the avoidance is the real problem. You are better of not trying to avoid instance methods.) (IMO,避免才是真正的问题。你最好不要试图避免实例方法。)

FWIW, you can declare static methods in an interface (since Java 8), but they would behave the same as if you declared them in a class. FWIW,您可以在接口中声明静态方法(自 Java 8 起),但它们的行为与您在类中声明它们的行为相同。 You wouldn't be able to dispatch ...你将无法派遣...

Write a wrapper interface编写包装接口

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

and wrapper class factory method for each Class containing the methods和包含方法的每个类的包装类工厂方法

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

Then you can use that:然后你可以使用它:

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