反射是框架设计的灵魂
软件框架:软件本成品,能够帮助我们提高开发效率。Spring,SpringMVC,Mybaties, Hadoop, Spark
反射的定义:讲类的各个组成部分封装为其他对象。这就是反射机制。
===========================================
Class字节码对象
反射可以帮助我们创建对象
获取类的字节码对象,有三种方式:
1.Source(源代码阶段):
Class.forName("全类名"); 将字节码文件加载进内存,返回Class对象,多用于配置文件,将类名定义在配置文件中,读取文件,加载类
如:Class.forName("reflect.demo01.Animal");
2.Class阶段:类名.class
通过类名的属性class获取,多用于方法的参数的传递。
如 Animal.class
3.Runtime运行时阶段:对象名.getClass();
getClass()方法在Object类中定义着,多用于对象的获取字节码的方式。
如:
Animal animal = new Animal();
animal.getClass();
package reflect.demo01;
public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException {
/**
* 想执行任何对象的任何方法
* 首先不知道对象,也不知道方法,此时可以用反射
* 使用反射创建对象,需要获取字节码,三个阶段有不通的获取方式
*
*/
Animal animal = new Animal(); //创建一个对象
//第一阶段:源代码阶段
Class cls1 = Class.forName("reflect.demo01.Animal"); //用copy reference的方式,需要抛出异常
//第二阶段:Class阶段
Class cls2 = Animal.class;
//第三阶段:Runtime阶段
Class cls3 = animal.getClass();
System.out.println(cls1 == cls2); //true
System.out.println(cls2 == cls3); //true
}
}
注意:
1.一个类对应在内存中对象的字节码对象,有且只有一个,以上三种方式获取的字节码对象都是同一个对象。
2.每个类都会有一个字节码对象
成员方法:
1.获取类的成员变量们
Field[] getFields() 获取类中被public关键字修饰的成员变量
Field getField(String name)获取类中指定名称的被public关键字修饰的成员变量
Field[] getDeclareFields() 获取类中所有成员变量(字段),不考虑权限修饰符
Field getDeclareField(String name) 获取类中指定的成员变量
注意:凡是带有Declared的方法获取除了的字段,如果是被private修饰的字段,可以通过暴力放射设置为ture给其赋值
格式:nameField.setAccessible(true);
Field nameField = personClass.getDeclaredField("name");
//暴力反射,能获取私有变量的值
nameField.setAccessible(true);
Person p = new Person();
nameField.set(p, "迪丽热巴");
System.out.println(p);
获取字段的目的:
获取值 field.get(对象)
设置值 field.set(对象,字段对应的值)
2.获取类的构造方法们
Constructor>[] getConstructors():获取类中所有被public修饰的构造方法
Constructor
Constructor>[] getDeclaredConstructors()
Constructor[] getDeclaredConstructors(类>... parameterTypes)
3.获取类的成员方法们
Method[] getMethods():获取类中所有被public修饰的成员方法
Method getMethod(String name, 类>... parameterTypes):获取类中指定名称的被public修饰的成员方法
Method[] getDeclaredMethods() 获取私有的方法
Method getDeclaredMethod(String name, 类>... parameterTypes)
4.获取类名
//获取Person类的字节码对象
Class personClass = Person.class;
//获取全类名 reflect.demo02.Person
System.out.println(personClass.getName());
//只获取类名 Person
System.out.println(personClass.getSimpleName());
package reflect.demo02;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 1.获取类的成员方法们
* Field[] getFields() 获取类中被public关键字修饰的成员变量
* Field getField(String name) 获取类中指定名称的被public关键字修饰的成员变量
*
* Field[] getDeclaredFields() 获取类中所有成员变量(字段),不考虑权限修饰符
* Field getDeclaredField(String name) 获取类中指定的成员变量
* 注意:凡是带有Declared的方法获取除了的字段,如果是被private修饰的字段,可以通过暴力放射设置为ture给其赋值
* 格式:Field nameField = personClass.getDeclaredField("name");
* //暴力反射,能获取私有变量的值
* nameField.setAccessible(true);
* Person p = new Person();
*
* nameField.set(p, "迪丽热巴");
* System.out.println(p);
*
* 获取字段:
* 获取值:field.get(对象)
* 设置值:field.set(对象,字段对应的值)
*/
public class Demo01 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//获取Person类的字节码对象
Class personClass = Person.class;
//获取全类名 reflect.demo02.Person
System.out.println(personClass.getName());
//只获取类名 Person
System.out.println(personClass.getSimpleName());
}
/**
* 获取类的成员方法们
* Method[] getMethods():获取类中所有被public修饰的成员方法
* Method getMethod(String name, 类>... parameterTypes):获取类中指定名称的被public修饰的成员方法
*
* Method[] getDeclaredMethods() 获取所有私有的方法,用到暴力反射
* Method getDeclaredMethod(String name, 类>... parameterTypes) 获取指定的私有方法
* 执行方法:方法名.invoke(对象)
*
* @throws NoSuchMethodException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
private static void getMethodsFromClass() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
//获取Person类的字节码对象
Class personClass = Person.class;
//获取类中所有的被public修饰的成员方法
Method[] methods = personClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//获取指定名称的被public修饰的成员方法
Method m1 = personClass.getMethod("eat");
System.out.println(m1);
//获取指定名称带参数的被public修饰的成员方法
Method m2 = personClass.getMethod("eat", String.class);
System.out.println(m2);
Person p = new Person();
//获取一个无参数成员方法并执行(执行一个对象)
m1.invoke(p);
//获取一个有参数的成员方法并执行
m2.invoke(p, "饭饭");
//获取私有的方法,并执行
Method m3 = personClass.getDeclaredMethod("eat", int.class);
//通过暴力反射访问私有方法
m3.setAccessible(true);
m3.invoke(p, 5);
}
/**
* 获取类的成员变量们:
* Field[] getFields() 获取类中被public关键字修饰的成员变量
* Field getField(String name)获取类中指定名称的被public关键字修饰的成员变量
*
* Field[] getDeclareFields() 获取类中所有成员变量(字段),不考虑权限修饰符
* Field getDeclareField(String name) 获取类中指定的成员变量
* 注意:凡是带有Declared的方法获取除了的字段,如果是被private修饰的字段,可以通过暴力放射设置为ture给其赋值
* @throws NoSuchFieldException
* @throws IllegalAccessException
*/
public static void getFieldsFromClass() throws NoSuchFieldException, IllegalAccessException {
//获取Person类的字节码对象
Class personClass = Person.class;
//通过Person类的字节码对象的getFields()方法,获取类中被public关键字修饰的成员变量:[nickName, tel]
Field[] fields = personClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("==========");
//Field getField(String name) 获取类中指定名称的被public关键字修饰的成员变量
Field field = personClass.getField("nickName");
System.out.println(field);
Person p = new Person();
System.out.println(p);
//给p这个对象的nickName的值设置为老k
field.set(p, "老k");
System.out.println(p);
//获取该字段的值
Object o = field.get(p);
System.out.println(o);
System.out.println("==========================");
// Field[] getDeclareFields() 获取类中所有成员变量(字段),不考虑权限修饰符
// Field getDeclareField(String name) 获取类中指定的成员变量
Field[] fieldsDeclared = personClass.getDeclaredFields();
for (Field fieldDeclared : fields) {
System.out.println(fieldDeclared);
}
Field nameField = personClass.getDeclaredField("name");
//暴力反射,能获取私有变量的值
nameField.setAccessible(true);
nameField.set(p, "迪丽热巴");
System.out.println(p);
}
/**
* 获取类的构造方法们
* Constructor>[] getConstructors():获取类中所有被public修饰的构造方法
* Constructor[] getConstructors(类>... parameterTypes):获取指定的被public修饰的构造方法
*
* Constructor>[] getDeclaredConstructors() 获取私有的构造方法
* Constructor[] getDeclaredConstructors(类>... parameterTypes)
* @throws NoSuchMethodException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws InstantiationException
*/
public static void getConstructorsFromClass() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取Person类的字节码对象
Class personClass = Person.class;
//获取Person类中的所有构造方法
Constructor[] constructors = personClass.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//获取指定的带参数的构造方法
Constructor ct1 = personClass.getConstructor(String.class, int.class);
System.out.println(ct1);
//创建一个对象,赋值并且强制类型转换成Person对象
Person p2 = (Person)ct1.newInstance("xm", 12);
System.out.println(p2);
//获取无参数的构造方法,创建对象
Constructor ct2 = personClass.getConstructor();
//创建一个对象,并且强制类型转换成Person对象
Person p1 = (Person)ct2.newInstance();
System.out.println(p1);
//获取私有的构造方法,通过暴力反射创建对象
Constructor declaredConstructor = personClass.getDeclaredConstructor(String.class);
declaredConstructor.setAccessible(true);
Person p3 = (Person)declaredConstructor.newInstance("xm");
System.out.println(p3);
System.out.println(declaredConstructor);
}
}