什么是反射,为什么它的用处很大?| Java Debug 笔记

本文正在参加「Java主题月 – Java Debug笔记活动」,详情查看<活动链接>

提问:什么是反射,为什么它的用处很大?

我对Java很感兴趣,但是我认为在任何一门语言中,它们的原理都是相同的。

回答一

反射用来描述能否检查同一系统(或自身)中其它代码的代码。

比如说,你在写Java时,碰到一个类型未知的对象,你想调用这个对象的doSomething()方法(如果存在的话)。Java的静态类型系统并不支持这个需求,除非这个对象有一个已知的接口。但是使用反射,你的代码可以查找出这个对象是否有一个名为doSomething()的方法,如果你愿意,就可以调用它。

下面是一个测试用例,假设这个对象名为foo

Method method = foo.getClass().getMethod("doSomething", null);
method.invoke(foo, null);
复制代码

Java中使用非常普遍的一个用例是——注解。比如说Junit4使用反射在类中查找带有@Test注释的方法,然后在单元测试时调用它们。

这里有一些很好的用例可供学习

http://docs.oracle.com/javase/tutorial/reflect/index.html
复制代码

最后,这些概念在其它支持反射的静态类型语言(比如C#)中非常相似。在动态类型语言中,这些用例不太必要。因为编译器允许在任何对象上调用任何方法,如果方法不存在,则在运行时失败。

检查系统中的代码并查看对象类型的能力不是反射,而是类型内省。反射就是在运行时通过内省进行修改的能力。这种区别在这里是必要的,因为有些语言支持反省,但不支持反射,比如C++。

回答二

反射允许在运行时动态实例化新对象、调用方法和对类变量执行get/set操作,而无需事先了解其实现。

Class myObjectClass = MyObject.class;
Method[] method = myObjectClass.getMethods();

//Here the method takes a string parameter if there is no param, put null.
Method method = aClass.getMethod("method_name", String.class); 

Object returnValue = method.invoke(null, "parameter-value1");
复制代码

在上面的代码中,null参数是你想调用的方法所属的对象。如果方法是静态的,则提供null。如果方法不是静态的,那么在调用时需要提供有效的MyObject实例而不是null

反射还允许你访问类的私有成员/方法:

public class A{

  private String str= null;

  public A(String str) {
  this.str= str;
  }
}
复制代码
A obj= new A("Some value");

Field privateStringField = A.class.getDeclaredField("privateString");

//Turn off access check for this field
privateStringField.setAccessible(true);

String fieldValue = (String) privateStringField.get(obj);
System.out.println("fieldValue = " + fieldValue);
复制代码

为了检查类(也称为内省),你不需要导入反射包(java.lang.reflect)。可以通过java.lang.Class访问类的元数据。

反射是一个非常强大的API,但如果使用过度,它可能会减慢应用程序的速度,因为它在运行时解析所有类型。

文章翻译自Stack Overflow:stackoverflow.com/questions/3…

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享