java中很多框架都用到了反射,所以在造spring轮子之前,还是要彻底的了解一下反射。
1.什么是反射?(what)
在学习任意一个技术时,我们可以去官网看它的介绍,而不是先去百度。
官网反射介绍:https://www.oracle.com/technetwork/articles/java/javareflection-1536171.html
介绍如下:
Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them。
反射式java编程语言的一个特性,它允许java程序在运行时进行自我检查并操作程序内部的属性。例如,对于java类我们可以获得它所有成员的名字并展示它们。
2.为什么会有反射?(why)
了解了什么事反射后,能知道我们可以通过反射获取类的所有成员和方法,并且调用,这就能做很多事情了。
3.怎么去使用反射?(How)
那么怎么调用呢?要先获取到该类的字节码文件对象,就是.class文件。 在程序运行期间,JVM始终为所有的对象维护一个类型标识,这个标识跟踪着这个对象所属的类,而保存这些信息的类就是Class类。
首先贴上我这里用于测试的简单Person类:
public class Person {
public String name;
public Person(String name){
this.name = name;
}
public Person(){}
public void say(){
System.out.println("I am a person,I can say Hello,World.");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
我们如何获取Class类呢?一般有三种方式:
//1.通过类.class语法,静态加载
Class clazz1 = Person.class;
System.out.println(clazz1);
//2.通过对象.getClass(),静态加载
Class clazz2 = new Person().getClass();
System.out.println(clazz2);
//3.通过Class.forName("限定类名"); 动态加载
Class clazz3 = Class.forName("com.jts.study.reflect.Person");
System.out.println(clazz3);
在开发中我们用反射都是用的第三种。因为前两种本来类就知道了,就没必要再用反射了。
获得Class类后,我们就可以做很多事情了。
几种常见的对类的类型的判断:
clazz.isInterface();//判断是否是接口
clazz.isAnnotation();//类型是否是注解
clazz.isArray();//类型是否是数组
clazz.isAnnotation();//判断是否是注解
//类上是否有JRequestMapping注解,我们使用的注解开发基本都是基于这个方法去判断的
clazz.isAnnotationPresent(JRequestMapping.class);
clazz.isEnum();//类型是否是枚举类型
clazz.isPrimitive();//类型是否是原始数据类(boolean,byte,short,char,int,float,double,long)
拿到一个类的class之后,如果去实例化这个类呢?
//如果是无参构造器,直接用clazz.newInstance()方法即可。
Person person = (Person)clazz.newInstance();
//如果是有参构造器,类似于这样的呢
Constructor constructor = clazz.getConstructor(String.class);
Person sss = (Person)constructor.newInstance("my name is lily");
System.out.println(sss.getName());
- 获取类的字段并调用,用Field类
Class<?> clazz = Class.forName("com.jts.study.reflect.Person");
Person person = (Person)clazz.newInstance();
Field field = clazz.getDeclaredField("name");
//getDeclaredField可以获取private 声明的变量,而getField不可以
field.setAccessible(true);//配合getDeclaredField()方法一起使用。
field.set(person,"field test"); //给字段赋值
System.out.println(person.getName());
//获取类的所有字段信息
Field[] declaredFields = clazz.getDeclaredFields();
- 获取类的方法并调用,用Method类
无参方法获取并调用:
Class<?> clazz = Class.forName("com.jts.study.reflect.Person");
Person person = (Person)clazz.newInstance();
person.setName("reflect method test");
Method getName = clazz.getDeclaredMethod("getName");//获取无参方法
Object result1 = getName.invoke(person);//无参方法调用(有返回值)
System.out.println(result1);
有参方法获取并调用:
Method setName = clazz.getDeclaredMethod("setName", String.class);//获取有参方法
setName.invoke(person, "set name test");//有参方法调用
System.out.println(person.getName());
总结:Java反射机制是指java程序在运行过程中,可以获取任意一个类的相关信息,并且能够调用其方法和属性。