1.反射机制定义
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改其本身状态或行为的一种能力。
在Java环境中,反射机制允许程序在执行时获取某个类自身的定义信息,例如熟悉和方法等也可以实现动态创建
类的对象、变更属性的内容或执行特定的方法的功能。从而使Java具有动态语言的特性,增强了程序的灵活性和
可移植性。
2.反射机制的作用
Java反射机制主要用于实现以下功能。
(1)在运行时判断任意一个对象所属的类型。
(2)在运行时构造任意一个类的对象。
(3)在运行时判断任意一个类所具有的成员变量和方法。
(4)在运行时调用任意一个对象的方法,甚至可以调用private方法。
注意:上述功能都是在运行时环境中,而不是在编译时环境中。
3.Java反射机制API
实现Java反射机制的API在Java.lang.reflect包下,具有以下几点。
(1)Class类:代表一个类。
(2)Filed类:代表类的成员变量。
(3)Method类:代表类的方法。
(4)Constructor类:代表类的构造方法。
(5)Array类:提供了动态创建数组及访问数组元素的静态方法。该类中的所有方法都是静态的。
4.应用示例
(1)根据类名获取类中定义的所有属性和方法,实例代码如下:
-
package day0105;
-
import java.lang.reflect.Array;
-
import java.lang.reflect.Field;
-
import java.lang.reflect.Method;
-
public class Reflect {
-
/**
-
*
-
*打印出String类所有的属性和方法
-
*/
-
public void test1(){
-
Class c = String.class;
-
Method[] methods = c.getMethods();
-
for(int i = 0;i<methods.length;i++){
-
System.out.println(methods[i].getName());
-
}
-
Field[] fields = c.getFields();
-
for(Field f : fields){
-
System.out.println(f.getType()+":"+f.getName());
-
}
-
}
-
/**
-
* 根据类名动态创建类的对象
-
* @throws Exception
-
*/
-
public void test2() throws Exception{
-
Class c = Class.forName("day0105.Student");
-
Student student = (Student)c.newInstance();
-
student.setName("java");
-
student.setId("1001");
-
student.show();
-
}
-
/**
-
* 根据类名和方法名,执行对象的方法
-
* @param student
-
* @param method
-
* @param value
-
* @throws Exception
-
*/
-
public void test3(Student student,String method,String value) throws Exception{
-
String s1 = method.substring(0,1).toUpperCase();
-
String s2 = method.substring(1);
-
String m = "set"+s1+s2;
-
System.out.println(m);
-
Class c = student.getClass();
-
Method set = c.getMethod(m,new Class[]{String.class});
-
set.invoke(student,new Object[]{value});
-
}
-
/**
-
* 动态创建数组对象,对数组元素复制和取值
-
*/
-
public void test4(){
-
try{
-
Class cls = Class.forName("java.lang.String");
-
//创建一个String类型的数组,大小为10
-
Object arr = Array.newInstance(cls, 10);
-
//在数组5索引的位置赋值
-
Array.set(arr, 5, "this is a test");
-
//获取数组5索引位置的值
-
String s = (String)Array.get(arr, 5);
-
System.out.println(s);
-
}catch(Throwable e){
-
System.out.println(e);
-
}
-
}
-
}
Student类的定义如下
-
package day0105;
-
public class Student {
-
private String id;
-
private String name;
-
public String getId() {
-
return id;
-
}
-
public void setId(String id) {
-
this.id = id;
-
}
-
public String getName() {
-
return name;
-
}
-
public void setName(String name) {
-
this.name = name;
-
}
-
public void show(){
-
System.out.println(id+":"+name);
-
}
-
}
Java语言反射提供一种动态链接程序组件的多功能方法。它允许程序创建和控制任何类的对象,
无需提前硬编码目标类。这些特性使得反射特别适用于创建以普通方式与对象协作的库。
反射在性能方面会有一定的损耗,用于字段和方法接入时反射要远慢于直接写代码。如果它作为程序
运行中相对很少涉及的部分将不会造成影响,因为即使测试最坏情况下的计时图显示的反射操作也只耗用几微秒。
1、什么是Java类中的反射?
当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。我们认为 Java 并不是动态语言,但是它却又一个非常突出的动态相关的机制,俗称:反射。
Reflection 是Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类和对象的内部属性。
Oracle 官方对反射解释:
image.png
通过反射,我们可以在运行时获得程序或程序集中每一个类型成员和成员变量的信息。
程序中一般的对象类型都是在编译期就确定下来的,而Java 反射机制可以动态的创建对象并调用其属性,这样对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象即使这个对象在编译期是未知的,
反射的核心:是 JVM 在运行时 才动态加载的类或调用方法或属性,他不需要事先(写代码的时候或编译期)知道运行对象是谁。
2、Java反射框架提供以下功能:
①、在运行时判断任意一个对象所属的类
②、在运行时构造任意一个类的对象
③、在运行时判断任意一个类所具有的成员变量和方法(通过反射设置可以调用 private)
④、在运行时调用人一个对象的方法
3、反射的主要用途
很多人都认为反射在实际Java中开发应用中并不广泛,其实不然。
当我们在使用 IDE(如 Eclipse\IDEA)时,当我们输入一个队长或者类并向调用它的属性和方法时,一按 (“.”)点号,编译器就会自动列出她的属性或方法,这里就会用到反射。
反射最重要的用途就是开发各种通用框架。
很多框架(比如 Spring)都是配置化的(比如通过 XML文件配置 JavaBean,Action之类的),为了保证框架的通用性,他们可能根据配置文件加载不同的对象或类,调用不同的方法,这个时候就必须用到反射——运行时动态加载需要加载的对象。
举一个例子,在运用Struts 2框架的开发中我们一般会在struts.xml里去配置Action,比如:
<action name="login"
class="org.ScZyhSoft.test.action.SimpleLoginAction"
method="execute">
<result>/shop/shop-index.jsp</result>
<result name="error">login.jsp</result>
</action>
配置文件与Action建立了一种映射关系,当View层发出请求时,请求会被StrutsPrepareAndExecuteFilter拦截,然后StrutsPrepareAndExecuteFilter会去动态地创建Action实例。
——比如我们请求login.action,那么StrutsPrepareAndExecuteFilter就会去解析struts.xml文件,检索action中name为login的Action,并根据class属性创建SimpleLoginAction实例,并用invoke方法来调用execute方法,这个过程离不开反射。
对与框架开发人员来说,反射虽小但作用非常大,它是各种容器实现的核心。而对于一般的开发者来说,不深入框架开发则用反射用的就会少一点,不过了解一下框架的底层机制有助于丰富自己的编程思想,也是很有益的。
4、反射的基本运用
以上我们提到了反射可以拟用于判断任意对象所属的类,获得 Class对象,构造人一个对象以及调用一个对象。这里我们介绍一下基本反射功能的事先(反射相关类一般都在 java.lang.relfect包里)。
①、获得 Class 对象
(1)、使用 Class类的 forName() 静态方法:
public static Class<?> forName(String className)
……
在JDBC开发中常用此方法加载数据库驱动:
……java
Class.forName(driver)
(2)、直接获取某一个对象的 class,比如:
Class<?> klass = int.class;
Class<?> classInt = Integer.TYPE;
(3)、调用某个对象的getClass() 方法,比如:
StringBuilder str = new StringBuilder("123");
Class<?> klass = str.getClass();
②、判断是否为某个类的实例
一般地,我们用 instanceof关键字来判断是否为某个类的实例。同时我们也可以借助反射中Class对象的 isInstance()方法来判断是否为某个类的实例,它是一个 Native 方法:
public native boolean isInstance(Object obj);
③、创建实例
通过反射来生成对象主要有两种方式。
(1)使用 Class 对象的 newInstance() 方法来创建对象对应类的实例。
Class<?> c = String.calss;
Object str = c.getInstance();
(2)、先通过 Class 对象获取制定的 Constructor 对象,在调用 Constructor 对象的 newInstance() 方法来创建实例。这种方法可以用指定的构造器构造类的实例。
//获取String所对应的Class对象
Class<?> c = String.class;
//获取String类带一个String参数的构造器
Constructor constructor = c.getConstructor(String.class);
//根据构造器创建实例
Object obj = constructor.newInstance("23333");
System.out.println(obj);
作者:南城刀
链接:https://www.jianshu.com/p/d6035d5d4d12
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。