这两种构造实例的方式之间的差异(反映和新)

时间:2015-10-12 08:56:07

标签: java reflection

我有一个Parent.class(用户和元素可以被任何类替换)

public abstract class Parent {
    User user;

    public void InitUser() {
        Fileds f = this.getClass().getDeclaredFields();

        for(int i=0; i<f.length; i++) {
             f[i].set(this, new Element(i));
        }
    }
}

Child.class

public class Child extends Parent {
    Element e1;
    Element e2;

    public Child(User user) {
       super();
        this.user = user;
    }    

    public void doSomethingUsingE1AndE2() {
         // do something by using e1 and e2, invoking user's methods.
         user.perform(e1);
         user.perform(e2);

    }
}

在我的Client.class中,构建和使用Child的以下两种方法之间是否存在任何差异?

1

public class Client() {
      User user = new User();
      Class childClass = Class.forName("com.xxx.Child");

      Constructor con = childClass .getConstructor(User.class);
      Object o = con.newInstance(user);
      Method initMethod = child.getSuperclass().getDeclaredMethod(
                        "InitUser");
      initMethod.invoke(o);

      Method keyMethod = child.getMethod("doSomethingUsingE1AndE2");

      keyMethod.invoke(o);
}

2

public class Client() {
      User user = new User();
      Child c = new Child(user);
      c.InitUser();
      c.doSomethingUsingE1AndE2();
}

非常感谢。

2 个答案:

答案 0 :(得分:2)

创作没有区别。一种是标准方式(),另一种是Reflection

但请记住

  

反思很强大,但不应随意使用。如果可以在不使用反射的情况下执行操作,则优选避免使用它。通过反射访问代码时,应牢记以下问题。

  • 绩效开销

  • 安全限制

  • 内部曝光

除非您没有其他选择,否则请始终尝试使用方式反思

答案 1 :(得分:1)

在行为上,它是相同的 - 对于这两种方法,您将拥有一个类的实例,并且您将调用一些实例方法。

然而,区别在于编译器的 use

当你反思性地创建一个类的实例,并在这个实例上反射性地调用某个方法时,编译器不会验证你所做的是正确的。避免编译器的帮助,您最终可能会在运行时遇到不同的错误,例如NoSuchMethodError(当您希望调用的方法不存在或无法调用时抛出),{{1} }和ReflectiveOperationException的其他子类。

遵循非反射方法,更安全 - 编译器可以验证您尝试执行的操作是否正确(方法是否可访问,参数是否有效等)并且会在之前抛出编译器错误该计划已经启动。

请注意,反射有时非常有用,但

  

...如果可以不使用反射执行操作,则最好避免使用它。