文章目录
- 1.快速入门
- 1.案例引入
- 2.代码实例
- 3.反射机制原理图
- 2.反射相关类
- 1.反射获取类的成员
- 代码实例
- 结果
- 2.反射调用优化
- 1.关闭访问检查
- 2.代码实例
- 3.Class类
- 1.类图
- 2.基本介绍
- 3.Class类常用方法
- 代码实例
- 结果
- 4.获取Class类对象
- 代码实例
- 结果
- 5.哪些类型有Class对象
- 4.类加载
- 1.基本介绍
- 2.静态加载与动态加载实例
- 3.类加载流程图
- 4.简要理解类加载
- 5.反射获取类的结构信息
- 第一组
- 代码实例
- 结果
- 第二组
- 代码实例
- 结果
- 第三组
- 代码实例
- 结果
- 第四组
- 代码实例
- 结果
- 6.反射爆破
- 1.反射爆破创建实例
- 代码实例
- 结果
- 2.反射爆破操作属性
- 代码实例
- 结果
- 3.反射爆破操作方法
- 代码实例
- 结果
- 7.本章练习
- 练习一
- 题目
- 代码
- 结果
- 练习二
- 题目
- 代码
- 结果
1.快速入门
1.案例引入
2.代码实例
package Reflection_;import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;/*** @author 孙显圣* @version 1.0*/
public class ReflectionQuestion {public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {//使用反射来根据配置文件来调用方法//1.读取配置文件,获取类的全路径和方法Properties properties = new Properties();properties.load(new FileInputStream("src\\cat.properties"));String fullclasspath = properties.getProperty("fullclasspath");String method = properties.getProperty("method");//2.加载类,返回Class类型的对象clsClass<?> cls = Class.forName(fullclasspath);//3.获取加载类的对象实例Object o = cls.newInstance();//4.获取加载类的方法对象Method method1 = cls.getMethod(method);//5.调用这个方法method1.invoke(o);}
}
3.反射机制原理图
2.反射相关类
1.反射获取类的成员
代码实例
package Reflection_;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;/*** @author 孙显圣* @version 1.0*/
public class Refection01 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {//类加载,获取Class类型Class<?> cls = Class.forName("Reflection_.Cat");//反射获取属性Field name = cls.getField("name"); //不能获取私有的System.out.println(name);//反射获取构造器Constructor<?> constructor = cls.getConstructor(String.class);System.out.println(constructor);//反射获取方法Method hi = cls.getMethod("hi");System.out.println(hi);}
}
结果
2.反射调用优化
1.关闭访问检查
- Method,Field,Constructor对象都有setAccessible方法
- setAccessible作用是启动和禁用访问安全检查的开关,true为取消
2.代码实例
package Reflection_;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;/*** @author 孙显圣* @version 1.0*/
public class Refection02 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {//传统方法来调用hinew Cat().hi();//使用反射来调用hiClass<?> cls = Class.forName("Reflection_.Cat");//获取方法对象Method hi = cls.getMethod("hi");//获取加载类的对象实例Object o = cls.newInstance();//关闭访问检查,提高速度hi.setAccessible(true);//执行方法hi.invoke(o);}
}
3.Class类
1.类图
2.基本介绍
- Class也是类,因此也继承Object类
- Class类对象不是new出来的,而是系统创建的
- 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
- 每个类的实例都会记得自己是由哪个Class实例所生成的
- 通过Class对象,可以完整地得到一个类的完整结构,通过一系列API
- Class类对象是放在堆的,可以理解为是把方法区中的元数据保存到Class类对象中,方便获取其中的成员
- 类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据
3.Class类常用方法
代码实例
package Reflection_;import java.lang.reflect.Field;/*** @author 孙显圣* @version 1.0*/
public class Class01 {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {//定义全路径String allClassPath = "Reflection_.Cat";//获取Cat类的Class类对象Class<?> cls = Class.forName(allClassPath);//显示该对象是哪个类的Class对象System.out.println(cls);//显示运行类型System.out.println(cls.getClass());//获取包名System.out.println(cls.getPackage().getName());//获取全类名System.out.println(cls.getName());//通过反射创建对象Cat o = (Cat) cls.newInstance();o.hi(); //调用Cat类的方法//通过反射获取属性Field name = cls.getField("name");//通过反射给属性赋值name.set(o,"小猫");System.out.println(name.get(o));//遍历所有属性Field[] fields = cls.getFields();for (Field field : fields) {System.out.println(field.get(o));}}
}
结果
4.获取Class类对象
代码实例
package Reflection_;/*** @author 孙显圣* @version 1.0*/
public class Class02 {public static void main(String[] args) throws Exception {//获取反射对象的六种方式//1. Class.forNameString classAllPath = "Reflection_.Cat"; //一般通过读取配置文件获取,在框架中用的较多Class<?> aClass = Class.forName(classAllPath);//2. 类名.class,应用场景:用于参数传递System.out.println(Cat.class);//3. 对象.getClass(),应用场景:有对象实例,获取运行类型System.out.println(new Cat().getClass());//4. 通过类加载器获取ClassLoader classLoader = Cat.class.getClassLoader(); //获取类加载器Class<?> aClass1 = classLoader.loadClass(classAllPath);//5.基本数据类型 类型.classClass<Integer> integerClass = int.class;Class<Character> characterClass = char.class;System.out.println(integerClass);System.out.println(characterClass);//6.基本数据类型对应的包装类 类型.TYPEClass<Integer> type = Integer.TYPE;Class<Character> type1 = Character.TYPE;System.out.println(type);System.out.println(type1);}
}
结果
5.哪些类型有Class对象
4.类加载
1.基本介绍
- 静态加载:编译时加载相关的类,如果没有则报错
- 动态加载:运行时才加载需要的类,如果运行时不使用该类,即使不存在该类,则不报错,降低了依赖性
- 类加载时机:
- 当创建对象时
- 当子类被加载时,父类也会被加载
- 调用类中的静态成员时
- 通过反射(动态加载)
2.静态加载与动态加载实例
在这里如果没有Dog类则直接编译报错,但是如果没有Person类,只要不执行case2则不会报错
3.类加载流程图
4.简要理解类加载
- 加载:得到Class类对象
- 连接:静态默认初始化,常量直接初始化
- 合并初始化:将静态代码合并,根据语句内容进行初始化
5.反射获取类的结构信息
第一组
代码实例
package Reflection_;import org.junit.jupiter.api.Test;import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;/*** @author 孙显圣* @version 1.0*/
public class ReflectionUtils {public static void main(String[] args) {}@Testpublic void api_01() throws Exception {//得到Class对象Class<?> personCls = Class.forName("Reflection_.Person");// getName:获取全类名System.out.println(personCls.getName());// getSimpleName:获取简单类名System.out.println(personCls.getSimpleName());// getFields:获取所有public修饰的属性,包含父类以及本类的Field[] fields = personCls.getFields();for (Field field : fields) {System.out.println(field);}// getDeclaredFields:获取本类所有属性Field[] declaredFields = personCls.getDeclaredFields();for (Field declaredField : declaredFields) {System.out.println("本类所有属性:" + declaredField);}// getMethods:获取所有public修饰的方法,包括本类以及父类的Method[] methods = personCls.getMethods();for (Method method : methods) {System.out.println(method);}// getDeclaredMethods:获取本类所有方法Method[] declaredMethods = personCls.getDeclaredMethods();for (Method declaredMethod : declaredMethods) {System.out.println("本类所有方法:" + declaredMethod);}// getConstructors: 获取所有public修饰的构造器,包括本类的Constructor<?>[] constructors = personCls.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println(constructor);}// getDeclaredConstructors: 获取本类所有的构造器Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();System.out.println("本类所有构造器:" +declaredConstructors);// getPackage:以Package形式返回包信息System.out.println(personCls.getPackage());// getSuperClass:以Class形式返回父类信息System.out.println(personCls.getSuperclass());// getInterfaces:以Class[]形式返回接口信息Class<?>[] interfaces = personCls.getInterfaces();for (Class<?> anInterface : interfaces) {System.out.println("所有接口信息:" + anInterface);}// getAnnotations:以Annotation[]形式返回注解信息Annotation[] annotations = personCls.getAnnotations();for (Annotation annotation : annotations) {System.out.println(annotation);}}
}
interface B {}
class A {public String hobby;public void hi() {}}
@SuppressWarnings("all")
@Deprecated
class Person extends A implements B{//属性public String name;protected int age;String job;private double sal;//构造器//方法public void m1() {}protected void m2() {}void m3() {}private void m4() {}
}
结果
第二组
代码实例
@Testpublic void api_02() throws ClassNotFoundException {//得到Class对象Class<?> personCls = Class.forName("Reflection_.Person");Field[] declaredFields = personCls.getDeclaredFields();for (Field declaredField : declaredFields) {System.out.println("该类的字段名:" + declaredField.getName() +" 该类的修饰符int形式:" +declaredField.getModifiers() +" 该类的Class类型:" + declaredField.getType());}}
结果
第三组
代码实例
@Testpublic void api_03() throws ClassNotFoundException {//得到Class对象Class<?> personCls = Class.forName("Reflection_.Person");Method[] declaredMethods = personCls.getDeclaredMethods();for (Method declaredMethod : declaredMethods) {System.out.println("该类的方法名:" + declaredMethod.getName() +" 该类的方法修饰符int形式:" +declaredMethod.getModifiers() +" 该类的方法返回类型:" + declaredMethod.getReturnType());//获取参数类型数组Class<?>[] parameterTypes = declaredMethod.getParameterTypes();for (Class<?> parameterType : parameterTypes) {System.out.println("参数类型:" + parameterType);}}}
结果
第四组
代码实例
@Testpublic void api_04() throws ClassNotFoundException {//得到Class对象Class<?> personCls = Class.forName("Reflection_.Person");Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();for (Constructor<?> declaredConstructor : declaredConstructors) {System.out.println("该类的构造器名:" + declaredConstructor.getName() +" 该类的构造器int形式修饰符:" + declaredConstructor.getModifiers());Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();for (Class<?> parameterType : parameterTypes) {System.out.println("参数类型:" + parameterType);}}}
结果
6.反射爆破
1.反射爆破创建实例
代码实例
package Reflection_;import java.lang.reflect.Constructor;/*** @author 孙显圣* @version 1.0*/
public class CreateInstance {public static void main(String[] args) throws Exception {//获取Class类对象Class<?> userClass = Class.forName("Reflection_.User");//1.使用无参构造方法创建实例Object o = userClass.newInstance();System.out.println(o);//2.使用public的有参构造方法创建实例//获取有参构造器对象Constructor<?> constructor = userClass.getConstructor(String.class);//创建实例Object o1 = constructor.newInstance("小明");System.out.println(o1);//3.使用非public的有参构造方法创建实例//获取构造器Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(String.class, int.class);//反射爆破declaredConstructor.setAccessible(true);//创建实例Object o2 = declaredConstructor.newInstance("杰克", 20);System.out.println(o2);}
}
class User {private String name = "李华";private int age = 18;public User() {}public User(String name) {this.name = name;}private User(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}
结果
2.反射爆破操作属性
代码实例
package Reflection_;import java.lang.reflect.Field;/*** @author 孙显圣* @version 1.0*/
public class AccessProperty {public static void main(String[] args) throws Exception {//获取Class实例Class<Student> studentClass = Student.class;//反射创建一个实例Student student = studentClass.newInstance();//1.操作public的属性//获取public的属性Field age = studentClass.getField("age");//操作age.set(student, 100);System.out.println(age.get(student));//2.操作非public且静态的属性//获取私有属性Field name = studentClass.getDeclaredField("name");//反射爆破name.setAccessible(true);//操作name.set(null, "李华");System.out.println(name.get(null)); //注意这里是因为是静态的属性才能填null,如果不是静态的则必须填对象}
}
class Student {public int age;private static String name;@Overridepublic String toString() {return "Student{" +"age=" + age +'}';}
}
结果
3.反射爆破操作方法
代码实例
package Reflection_;import java.lang.reflect.Method;/*** @author 孙显圣* @version 1.0*/
public class AccessMethod {public static void main(String[] args) throws Exception {//获取Class对象Class<Boss> bossClass = Boss.class;//创建实例Boss boss = bossClass.newInstance();//1.操作public的方法//获取方法Method hi = bossClass.getMethod("hi", String.class);//操作hi.invoke(boss, "李华");//2.操作非public的方法//获取方法Method say = bossClass.getDeclaredMethod("say", int.class, String.class, char.class);//爆破say.setAccessible(true);//操作Object invoke = say.invoke(null, 1, "2", '3');//注意,因为这里是静态的方法所以才能是nullSystem.out.println(invoke);}
}class Boss {public int age;private static String name;private static String say(int n, String s, char c) {return n + "" + s + "" + c;}public void hi(String s) {System.out.println("hi:" + s);}
}
结果
7.本章练习
练习一
题目
代码
package Reflection_;import java.lang.reflect.Field;/*** @author 孙显圣* @version 1.0*/
public class HomeWork01 {public static void main(String[] args) throws Exception{//获取Class类Class<PrivateTest> privateTestClass = PrivateTest.class;//创建实例PrivateTest privateTest = privateTestClass.newInstance();//获取属性Field name = privateTestClass.getDeclaredField("name");//反射爆破name.setAccessible(true);//修改属性name.set(privateTest, "cat");//输出属性System.out.println(name.get(privateTest));}
}class PrivateTest {private String name = "hellokitty";public String getName() {return name;}
}
结果
练习二
题目
代码
package Reflection_;import java.io.File;
import java.lang.reflect.Constructor;/*** @author 孙显圣* @version 1.0*/
public class HomeWork02 {public static void main(String[] args) throws Exception{//获取File类的Class对象Class<File> fileClass = File.class;//打印所有构造器Constructor<?>[] declaredConstructors = fileClass.getDeclaredConstructors();for (Constructor<?> declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor);}//获取构造器Constructor<File> declaredConstructor = fileClass.getDeclaredConstructor(String.class);//创建实例File file = declaredConstructor.newInstance("src\\Reflection_\\a.txt");file.createNewFile();}
}