Java反射 - 通过类名字符串获取级别

时间:2011-08-19 12:46:03

标签: java android reflection

我一直在研究Java反思。这是维基百科http://en.wikipedia.org/wiki/Reflection_(computer_programming)的一个例子:

// Without reflection
new Foo().hello();

// With reflection
Class<?> cls = Class.forName("Foo");
cls.getMethod("hello").invoke(cls.newInstance());

我发现这有点违反直觉,因为在创建实例之前会调用该方法。

当然,反思可以用来调用游戏等级,特别是如果它们有数百个。

编辑 - 一些解决方案:

以下是一个适用于Android的反射的简单示例:

    try {                
        Class<?> clazz = Class.forName("com.test.Foo");                
        clazz.newInstance();            
    } catch (Exception e) {                
        throw new IllegalStateException(e);            
    }

和类文件

public class Foo {

    Foo(){  
        hello();    
    }

    private void hello() {  
        Log.e("FOO", "Hello!");
    }
}

假设有人想通过反思调用一个Activity:

Activity activity;
try {                
  Class<?> clazz = Class.forName("com.test.MyLevelActivity");                
  activity = (Activity) clazz.newInstance();            
} catch (Exception e) {                
  throw new IllegalStateException(e);            
}
startActivity(new Intent(this,activity.getClass()));

假设应该通过反射“加载”包含数据和方法的级别:

    Level currentLevel;
    try {                
        Class<?> clazz = Class.forName("com.test.Level_1_1");                
        currentLevel = (Level) clazz.newInstance();            
    } catch (Exception e) {                
        throw new IllegalStateException(e);            
    }

    String levelName = currentLevel.getLevelName();
    String result = Integer.toString(currentLevel.processData(3, 7));

    Toast.makeText(this, levelName + " result= " + result, Toast.LENGTH_LONG).show();

以下是课程:

public abstract class Level {

   public abstract String getLevelName();

   public abstract int processData(int a, int b);

}


public class Level_1_1 extends Level{
   private String levelName = "level 1.1";

   public String getLevelName(){
      return levelName;
   }

   public int processData(int a, int b) {
      return a * b;
  }
} 

4 个答案:

答案 0 :(得分:7)

  

我发现这有点违反直觉,因为在创建实例

之前调用该方法

抱歉,不要这么认为。方法参数在传递给“invoke”之前首先被评估,因此最终将Foo类的“new”实例传递给Method类的“invoke”方法。另外,如果你想知道为什么在方法对象上调用“invoke”,那是因为对于给定的类,你只创建Method个对象一次,所有后续的调用都依赖于它的“状态”。对象而不是被调用的“方法”。

答案 1 :(得分:3)

这里

foo.hello();

无法正常工作,foo只是一个没有方法hello()的对象。

不熟悉的事情可能看似违反直觉,但最终新的习语变得自然。只需采用标准方法。

要理解它,请考虑方法定义不是对象的一部分,为类创建一次方法,它“独立于任何给定对象”。因此,对于班级说“嘿方法,在这个对象的背景下应用自己,他是我们中的一员”是非常合理的

答案 2 :(得分:2)

你的意思并不是很清楚,但这有帮助吗?

Class<?> cls = Class.forName("Foo");
Method method = cls.getMethod("hello");

Object instance = cls.newInstance();
method.invoke(instance);

答案 3 :(得分:1)

你没有先调用这个方法。你只是定义方法,然后调用它。另外,cls的实例是在我们实际进入invoke之前创建的。我发现反射在java中是一个非常有用的API,几乎所有在java上使用的framworks都使用它,如struts,log4j等。在反射中,你总是定义你想要调用的方法,然后才能处理实际的对象你想经营。

希望这有帮助!