如何在Java中将类作为参数传递?

175

在Java中有没有一种可以将类作为参数传递,并执行该类中的一些方法的方法?

void main()
{
    callClass(that.class)
}

void callClass(???? classObject)
{
    classObject.somefunction
    // or 
    new classObject()
    //something like that ?
}

我正在使用 Google Web Toolkit,它不支持反射。

11个回答

156
public void foo(Class c){
        try {
            Object ob = c.newInstance();
        } catch (InstantiationException ex) {
            Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

如何使用反射调用方法

 import java.lang.reflect.*;


   public class method2 {
      public int add(int a, int b)
      {
         return a + b;
      }

      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("method2");
           Class partypes[] = new Class[2];
            partypes[0] = Integer.TYPE;
            partypes[1] = Integer.TYPE;
            Method meth = cls.getMethod(
              "add", partypes);
            method2 methobj = new method2();
            Object arglist[] = new Object[2];
            arglist[0] = new Integer(37);
            arglist[1] = new Integer(47);
            Object retobj 
              = meth.invoke(methobj, arglist);
            Integer retval = (Integer)retobj;
            System.out.println(retval.intValue());
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

另请参阅


我该如何触发默认构造函数或类中的某些方法? - user562350
抱歉,我忘记提到 Google Web Toolkit 了,我正在使用 Google Web Toolkit,但它不支持反射。 - user562350
1
请查看这里这里,还有这个 - jmj
我想谈谈哲学!在Java中,Class是一种数据类型吗? - Milad Rahimi

50
public void callingMethod(Class neededClass) {
    //Cast the class to the class you need
    //and call your method in the class
    ((ClassBeingCalled)neededClass).methodOfClass();
}
调用该方法的方式如下:
callingMethod(ClassBeingCalled.class);

提问者还想使用类的构造函数。这并不容易,也没有人在这里解决它。这篇文章提供了一个选项(请阅读所有评论,因为被接受的答案不起作用):https://dev59.com/b3VC5IYBdhLWcg3woCnN。然而,这相当混乱,你得到的编译器警告表明他们不希望人们用Java做这个。在Python中更容易 :) - Andrew Puglionesi

29
构建您的方法来接受它 -
public <T> void printClassNameAndCreateList(Class<T> className){
    //example access 1
    System.out.print(className.getName());

    //example access 2
    ArrayList<T> list = new ArrayList<T>();
    //note that if you create a list this way, you will have to cast input
    list.add((T)nameOfObject);
}

调用这个方法-
printClassNameAndCreateList(SomeClass.class);

您还可以限制类的类型,例如,这是我制作的库中的一个方法-

protected Class postExceptionActivityIn;

protected <T extends PostExceptionActivity>  void  setPostExceptionActivityIn(Class <T> postExceptionActivityIn) {
    this.postExceptionActivityIn = postExceptionActivityIn;
}

要了解更多信息,请搜索"反射"和"泛型"。


4

将返回类型添加为 <T> T 对我有用。例如,使用json反序列化

 public static <T> T fromJson(String json, Class<T> classOfT){
     return gson().fromJson(json, classOfT);
 }

3

使用

void callClass(Class classObject)
{
   //do something with class
}

Class是Java中的一个对象,因此您可以使用其类型来引用它。

请从官方文档中了解更多信息。


2

这种事情并不容易。以下是一种调用静态方法的方法:

public static Object callStaticMethod(
    // class that contains the static method
    final Class<?> clazz,
    // method name
    final String methodName,
    // optional method parameters
    final Object... parameters) throws Exception{
    for(final Method method : clazz.getMethods()){
        if(method.getName().equals(methodName)){
            final Class<?>[] paramTypes = method.getParameterTypes();
            if(parameters.length != paramTypes.length){
                continue;
            }
            boolean compatible = true;
            for(int i = 0; i < paramTypes.length; i++){
                final Class<?> paramType = paramTypes[i];
                final Object param = parameters[i];
                if(param != null && !paramType.isInstance(param)){
                    compatible = false;
                    break;
                }

            }
            if(compatible){
                return method.invoke(/* static invocation */null,
                    parameters);
            }
        }
    }
    throw new NoSuchMethodException(methodName);
}

更新: 等等,我刚看到问题中有gwt标签。在GWT中无法使用反射。


1

我不确定你想要实现什么,但是你可能需要考虑到通过传递一个类来解决问题并不是你真正需要做的事情。在许多情况下,像这样处理类可以很容易地封装在某种类型的工厂模式中,并且使用该模式通过接口完成。以下是关于该模式的数十篇文章之一:http://today.java.net/pub/a/today/2005/03/09/factory.html

在工厂中使用类可以通过多种方式实现,最常见的方式是使用包含实现所需接口的类名称的配置文件。然后,工厂可以从类路径中找到该类并将其构造为指定接口的对象。


0

正如你所说,GWT不支持反射。你应该使用延迟绑定来代替反射,或者使用第三方库,例如gwt-ent,以在GWT层面上获得反射支持。


-1

-1

OP明确表示他正在使用不支持反射的GWT。 - Knarf
2
问题在我的回答之后被编辑了很久。原始问题并没有包含那个提示。另外,被接受的答案也涉及到反射。 - Marcus Gründler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接