什么是反思,为什么它有用?
我对Java特别感兴趣,但我认为任何语言的原理都是一样的。
什么是反思,为什么它有用?
我对Java特别感兴趣,但我认为任何语言的原理都是一样的。
当前回答
例子:
以一个远程应用程序为例,它为您的应用程序提供了一个对象,您可以使用其API方法获取该对象。现在,基于对象,您可能需要执行某种计算。
提供者保证对象可以是3种类型,我们需要根据对象的类型进行计算。
因此,我们可以在3个类中实现,每个类包含不同的逻辑。显然,对象信息在运行时可用,因此您无法静态编码以执行计算,因此反射用于实例化类的对象,您需要根据从提供程序接收的对象执行计算。
其他回答
反射是一种API,用于在运行时检查或修改方法、类和接口的行为。
反射所需的类在java.lang.reflect包中提供。反射为我们提供了有关对象所属的类的信息,以及可以使用该对象执行的该类的方法。通过反射,我们可以在运行时调用方法,而不考虑与它们一起使用的访问说明符。
java.lang和java.lang.reflect包为java反射提供了类。
反射可用于获取以下信息:
类getClass()方法用于获取对象所属类的名称。构造函数getConstructors()方法用于获取对象所属类的公共构造函数。方法getMethods()方法用于获取对象所属类的公共方法。
反射API主要用于:
IDE(集成开发环境),例如Eclipse、MyEclipse、NetBeans等。调试器和测试工具等。
使用反射的优点:
可扩展性特性:应用程序可以通过使用扩展性对象的完全限定名称创建扩展性对象实例来使用外部用户定义的类。
调试和测试工具:调试器使用反射属性来检查类上的私有成员。
缺点:
性能开销:反射操作的性能低于非反射操作,应避免在性能敏感应用程序中频繁调用的代码段中使用。
内部暴露:反射代码打破了抽象,因此可能会随着平台的升级而改变行为。
参考:Java Reflection javareviewed.blogspot.in
我觉得最好用例子来解释,但没有一个答案能做到这一点。。。
使用反射的一个实际例子是用Java编写的Java语言服务器或用PHP编写的PHP语言服务器等。语言服务器为您的IDE提供自动完成、跳转到定义、上下文帮助、提示类型等功能。为了让所有标记名(可以自动完成的单词)在键入时显示所有可能的匹配项,语言服务器必须检查类的所有内容,包括文档块和私有成员。为此,它需要对所述阶级的反思。
另一个例子是私有方法的单元测试。这样做的一种方法是创建一个反射,并在测试的设置阶段将方法的范围更改为公开。当然,有人会认为不应该直接测试私有方法,但这不是重点。
我想举个例子来回答这个问题。首先,Hibernate项目使用反射API生成CRUD语句,以弥合运行应用程序和持久性存储之间的鸿沟。当域中的情况发生变化时,Hibernate必须了解这些情况,才能将其持久化到数据存储中,反之亦然。
另外,Lombok项目也可以。它只是在编译时注入代码,导致代码被插入到域类中。(我认为这对getter和setter来说是可以的)
Hibernate选择反射是因为它对应用程序的构建过程影响最小。
在Java7中,我们有MethodHandles,它用作反射API。在项目中,要使用记录器,我们只需复制粘贴下一个代码:
Logger LOGGER = Logger.getLogger(MethodHandles.lookup().lookupClass().getName());
因为在这种情况下很难出错。
根据我的理解:
反射允许程序员动态访问程序中的实体。也就是说,当程序员对应用程序进行编码时,如果不知道类或其方法,他可以通过使用反射来动态地(在运行时)使用此类类。
它经常用于类名频繁更改的场景。如果出现这种情况,那么程序员重写应用程序并一次又一次地更改类的名称是很复杂的。
相反,通过使用反射,需要担心类名可能会发生变化。
反射允许在运行时动态实例化新对象、调用方法和获取/设置类变量的操作,而无需事先了解其实现。
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,但如果过度使用,它可能会降低应用程序的速度,因为它在运行时解析所有类型。