概述
引入
package ref;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Properties;public class Ref {public static void main(String[] args) throws Exception {//加载propertiesProperties properties = new Properties();properties.load(new FileInputStream("src\\re.properties"));String calsspath= properties.getProperty("classpath");String methodName=properties.getProperty("method");// System.out.println(method);// System.out.println(calss);//使用反射机制解决//(1) 加载类, 返回Class类型的对象clsClass cls=Class.forName(calsspath);//实例化对象Object o = cls.newInstance();//通过 cls 得到你加载的类 com.hspedu.Cat 的 methodName"hi" 的方法对象//即:在反射中,可以把方法视为对象(万物皆对象Method method = cls.getMethod(methodName);method.invoke(o); //传统方法 对象.方法() , 反射机制 方法.invoke(对象)//得到字段//getfield 不能得到私有的字段,只能得到共有的字段// Field name = cls.getField("name");Field age = cls.getField("age");System.out.println(age.get(o));//得到构造器Constructor constructor = cls.getConstructor();//()中可以指定参数,返回无参构造器Constructor constructor1 = cls.getConstructor(String.class);//String.class 就是 String类的class 对象System.out.println(constructor1);}}
原理
优化
优缺点
优点:
- 可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就是去底层支持
缺点:
- 使用反射基本是解释执行,对执行速度有影响
- 反射调用方法时可以忽略权限检查,获取这个类的私有方法和属性,因此可能会破坏类的封装性而导致安全问题。
Class类
常用方法
类型 | 访问方法 | 返回值类型 | 说明 |
---|---|---|---|
包路径 | getPackage() | Package 对象 | 获取该类的存放路径 |
类名称 | getName() | String 对象 | 获取该类的名称 |
继承类 | getSuperclass() | Class 对象 | 获取该类继承的类 |
实现接口 | getlnterfaces() | Class 型数组 | 获取该类实现的所有接口 |
构造方法 | getConstructors() | Constructor 型数组 | 获取所有权限为 public 的构造方法 |
getDeclaredContruectors() | Constructor 对象 | 获取当前对象的所有构造方法 | |
方法 | getMethods() | Methods 型数组 | 获取所有权限为 public 的方法 |
getDeclaredMethods() | Methods 对象 | 获取当前对象的所有方法 | |
成员变量 | getFields() | Field 型数组 | 获取所有权限为 public 的成员变量 |
getDeclareFileds() | Field 对象 | 获取当前对象的所有成员变量 | |
内部类 | getClasses() | Class 型数组 | 获取所有权限为 public 的内部类 |
getDeclaredClasses() | Class 型数组 | 获取所有内部类 | |
内部类的声明类 | getDeclaringClass() | Class 对象 | 如果该类为内部类,则返回它的成员类,否则返回 null |
String classpath="learn.Car";//<?>代表不确定的clsClass<?> cls = Class.forName(classpath);System.out.println(cls);//显示的时cls对象是那个类的Class对象 class learn.CarSystem.out.println(cls.getClass());//显示的是cls的运行类型class java.lang.Class//得到包名System.out.println(cls.getPackage());//package learnSystem.out.println(cls.getPackage().getName());//learn//得全类名System.out.println(cls.getName());//learn.Car//通过cls创建实例Car car = (Car)cls.newInstance();car.setName("宝马");System.out.println(car.getName());//获取属性,但属性要是共有的Field weight = cls.getField("weight");System.out.println(weight.get(car));//设置属性weight.set(car,200);System.out.println(weight.get(car));//得到所有的字段属性,也是publicField[] fields = cls.getFields();System.out.println(fields.length);//1for (Field field:fields) {System.out.println(field.getName());}
得到Class对象的方法
//1.Class.forName 往往通过配置文件读取到String classpath="learn.Car";Class<?> cls = Class.forName(classpath);System.out.println(cls);System.out.println(cls.hashCode());//2.类名.class 多用于参数传递Class<Car> cls2 = Car.class;System.out.println(cls2);System.out.println(cls2.hashCode());//3.通过对象名来获取 对象名.getclasCar car=new Car();Class cls3=car.getClass();System.out.println(cls3);System.out.println(cls3.hashCode());//4.通过类加载器(4种),来获取// 1,先得到类加载器ClassLoader classLoader = car.getClass().getClassLoader();// 2,通过类加载器得到类对象Class<?> cls4= classLoader.loadClass(classpath);System.out.println(cls4);System.out.println(cls4.hashCode());//5.基本数据类型也可以 int.classClass<Integer> integerClass = int.class;System.out.println(integerClass);//int//6.基本数据类型的包装类 Integer.TYPEClass<Integer> type = Integer.TYPE;System.out.println(type);//intSystem.out.println(integerClass.hashCode());System.out.println(type.hashCode());//Integer.TYPE和int.class二者是一样的,底层通过拆箱和装箱是同一个
那些类型有Class对象
Class<String> stringClass = String.class;//外部类Class<Serializable> serializableClass = Serializable.class;//接口类Class<int[]> aClass = int[].class;//数组类Class<Deprecated> deprecatedClass = Deprecated.class;//注解类Class<Thread.State> stateClass = Thread.State.class;//枚举类Class<Integer> integerClass = int.class;//基本数据类型类Class<Integer> integerClass1 = Integer.class;//基本数据类型包装类类Class<Void> voidClass = void.class;//void 类Class<Class> classClass = Class.class;//Class类,也是一种外部类
通过反射获取类的结构信息
Class类
package class_;import org.junit.Test;import java.lang.annotation.Annotation;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class Class07 {public static void main(String[] args) {}@Testpublic void api01() throws ClassNotFoundException {Class<?> peopleClass = Class.forName("class_.People");//获得全类名System.out.println(peopleClass.getName());//class_.People//获得简单类名System.out.println(peopleClass.getSimpleName());//people//获取本类以及父类的所有公共属性Field[] fields = peopleClass.getFields();for (Field field:fields) {System.out.println(field.getName());}//获取本类的所有属性,包括私有等System.out.println("===");Field[] declaredFields = peopleClass.getDeclaredFields();for (Field field:declaredFields) {System.out.println(field.getName());}//获取本类及父类的public方法,不限于直接父类System.out.println("====");Method[] methods = peopleClass.getMethods();for (Method method : methods) {System.out.println(method.getName());}//获取本类的所有方法System.out.println("=====");Method[] declaredMethods = peopleClass.getDeclaredMethods();for (Method declaredMethod : declaredMethods) {System.out.println(declaredMethod.getName());}//获取本类的所有public构造器,没有父类System.out.println("=====");Constructor<?>[] constructors = peopleClass.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println(constructor.getName());}//获取本类的所有方法,不局限于publicSystem.out.println("+++");Constructor<?>[] declaredConstructors = peopleClass.getDeclaredConstructors();for (Constructor<?> declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor.getName());}//得到包名System.out.println(peopleClass.getPackage());//package class_//得到父类的信息System.out.println(peopleClass.getSuperclass());//class class_.Animal//返回接口Class<?>[] interfaces = peopleClass.getInterfaces();for (Class<?> anInterface : interfaces) {System.out.println(anInterface.getName());}//返回注解Annotation[] annotations = peopleClass.getAnnotations();for (Annotation annotation : annotations) {System.out.println(annotation);}}}interface IFA {}interface IFB {}class Animal{public String hobby;public void hi() {}public Animal() {}public Animal(String hobby) {}}@Deprecatedclass People extends Animal implements IFA,IFB{//属性public String name;protected static int age; // 4 + 8 = 12String job;private double sal;//构造器public People(){}public People(String name) {}//私有的private People(String name, int age) {}//方法public void m1(String name, int age, double sal) {}protected String m2() {return null;}void m3() {}private void m4() {}}
Filed类,Method类
package class_;import org.junit.Test;import java.lang.annotation.Annotation;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class Class07 {public static void main(String[] args) {}@Testpublic void api01() throws ClassNotFoundException {Class<?> peopleClass = Class.forName("class_.People");//获得全类名System.out.println(peopleClass.getName());//class_.People//获得简单类名System.out.println(peopleClass.getSimpleName());//people//获取本类以及父类的所有公共属性Field[] fields = peopleClass.getFields();for (Field field:fields) {System.out.println(field.getName());}//获取本类的所有属性,包括私有等System.out.println("===");Field[] declaredFields = peopleClass.getDeclaredFields();for (Field field:declaredFields) {System.out.println(field.getName());}//获取本类及父类的public方法,不限于直接父类System.out.println("====");Method[] methods = peopleClass.getMethods();for (Method method : methods) {System.out.println(method.getName());}//获取本类的所有方法System.out.println("=====");Method[] declaredMethods = peopleClass.getDeclaredMethods();for (Method declaredMethod : declaredMethods) {System.out.println(declaredMethod.getName());}//获取本类的所有public构造器,没有父类System.out.println("=====");Constructor<?>[] constructors = peopleClass.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println(constructor.getName());}//获取本类的所有方法,不局限于publicSystem.out.println("+++");Constructor<?>[] declaredConstructors = peopleClass.getDeclaredConstructors();for (Constructor<?> declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor.getName());}//得到包名System.out.println(peopleClass.getPackage());//package class_//得到父类的信息System.out.println(peopleClass.getSuperclass());//class class_.Animal//返回接口Class<?>[] interfaces = peopleClass.getInterfaces();for (Class<?> anInterface : interfaces) {System.out.println(anInterface.getName());}//返回注解Annotation[] annotations = peopleClass.getAnnotations();for (Annotation annotation : annotations) {System.out.println(annotation);}}@Testpublic void api02() throws ClassNotFoundException {Class<?> peopleClass = Class.forName("class_.People");//获取本类中所有的属性Field[] declaredFields = peopleClass.getDeclaredFields();for (Field declaredField : declaredFields) {System.out.println("本类中的属性:"+declaredField.getName()+"该属性的修饰符:"+declaredField.getModifiers()+" 该属性的类型"+declaredField.getType());}}@Testpublic void api03() throws ClassNotFoundException {Class<?> peopleClass = Class.forName("class_.People");//获取本类中所有的方法Method[] declaredMethods = peopleClass.getDeclaredMethods();for (Method declaredMethod : declaredMethods) {System.out.println("该类的方法"+declaredMethod.getName()+"该属性的修饰符:"+declaredMethod.getModifiers()+"该类的返回类型"+declaredMethod.getReturnType());Class<?>[] parameterTypes = declaredMethod.getParameterTypes();for (Class<?> parameterType : parameterTypes) {System.out.println("该方法的参数类型"+parameterType.getName());}}}@Testpublic void api04() throws ClassNotFoundException {Class<?> peopleClass = Class.forName("class_.People");//获取本类中所有的构造器Constructor<?>[] declaredConstructors = peopleClass.getDeclaredConstructors();for (Constructor<?> declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor);System.out.println(declaredConstructor.getName());//名字System.out.println(declaredConstructor.getModifiers());//修饰符System.out.println(declaredConstructor.getParameterCount());//参数个数}}}interface IFA {}interface IFB {}class Animal{public String hobby;public void hi() {}public Animal() {}public Animal(String hobby) {}}@Deprecatedclass People extends Animal implements IFA,IFB{//属性public String name;protected static int age; // 4 + 8 = 12String job;private double sal;//构造器public People(){}public People(String name) {}//私有的private People(String name, int age) {}//方法public void m1(String name, int age, double sal) {}protected String m2() {return null;}void m3() {}private void m4() {}}
动态加载和静态加载
package class_;import learn.Car;import javax.management.MBeanRegistration;import java.util.Scanner;public class Class05 {public static void main(String[] args) throws ClassNotFoundException {Scanner scanner=new Scanner(System.in);String key=scanner.next();switch (key){case "1"://静态加载,如果没有import learn.Car,编译javac就会报错Car car =new Car();case "2"://动态加载,javac编译不会报错Class<?> aClass = Class.forName("learn.Cat");break;}}}
类加载
类加载前两个阶段由JVM控制,初始化是由程序员控制,主要是静态成员
- 加载loading
- JVM在该阶段的主要目的是将字节码从 不同的数据源(可能是class文件,也可能是jar包,甚至是网络)转换成二进制字节流加载到内存(方法区中)并生成一个该类的java.lang.Class对象(堆中)
- 连接Linking
- 验证verification
- 目的是为了确保Class文件的字节流中包含的信息复合当前虚拟机的要求,并且不会危害虚拟机自身的安全
- 包括:文件格式验证(是否以魔数 oxcafebage开头)、元数据验证、字节码验证和符号引用验证
- 可以考虑使用 -Xverify:none 参数来关闭大部分的类验证措施,缩短虚拟机加载的时间
- 准备preparation
- JVM会在该阶段对静态变量,分配内存并默认初始化(对应数据类型的默认初始化值,eg.0,0L,null,false等)(和Class对象一起存放在堆中)
- 解析resolution
- 虚拟机将常量池内的符号引用替换为直接引用的过程
- 即在编译阶段,并没有放到内存中没有内存地址,所以引用是符号引用;在解析这一步把符号引用替换为直接引用
- 验证verification
- 初始化initialization
- 到初始化阶段,才开始执行类中定义的Java代码,此阶段执行clinit()方法的过程
- clinit()方法是由编译器按照语句在源文件中出现的顺序,一次自动收集类中所有的静态变量的赋值动作和静态代码块中的语句,并进行合并
- 虚拟机会保证一个类的clinit()方法在多线程环境中被正确的加锁,同步,如果多个线程同时去初始化一个类,俺么只会有一个线程去执行这个类的clint()方法
通过反射创建对象
package class_;import org.junit.Test;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;public class calss08 {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {//得到Class对象Class<?> cls = Class.forName("class_.User");//通过public的无参构造器创建对象Object o = cls.newInstance();System.out.println(o);//通过public的有参构造器创建实例//先获得有参构造器,才创建实例Constructor<?> constructor = cls.getConstructor(String.class);Object zhang = constructor.newInstance("zhang");System.out.println(zhang);//通过private的有参构造器Constructor<?> declaredConstructor = cls.getDeclaredConstructor(int.class, String.class);declaredConstructor.setAccessible(true);//爆破,使用返反射可以用private构造器Object baby = declaredConstructor.newInstance(2, "baby");System.out.println(baby);}}class User { //User类private int age = 10;private String name = "gao";public User() {//无参 public}public User(String name) {//public的有参构造器this.name = name;}private User(int age, String name) {//private 有参构造器this.age = age;this.name = name;}public String toString() {return "User [age=" + age + ", name=" + name + "]";}}
类的成员和方法
package com.hspedu.reflection;import java.lang.reflect.Field;/*** @author 韩顺平* @version 1.0* 演示反射操作属性*/public class ReflecAccessProperty {public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {//1. 得到Student类对应的 Class对象Class<?> stuClass = Class.forName("com.hspedu.reflection.Student");//2. 创建对象Object o = stuClass.newInstance();//o 的运行类型就是StudentSystem.out.println(o.getClass());//Student//3. 使用反射得到age 属性对象Field age = stuClass.getField("age");age.set(o, 88);//通过反射来操作属性System.out.println(o);//System.out.println(age.get(o));//返回age属性的值//4. 使用反射操作name 属性Field name = stuClass.getDeclaredField("name");//对name 进行暴破, 可以操作private 属性name.setAccessible(true);//name.set(o, "老韩");name.set(null, "老韩~");//因为name是static属性,因此 o 也可以写出nullSystem.out.println(o);System.out.println(name.get(o)); //获取属性值System.out.println(name.get(null));//获取属性值, 要求name是static}}class Student {//类public int age;private static String name;public Student() {//构造器}public String toString() {return "Student [age=" + age + ", name=" + name + "]";}}
package com.hspedu.reflection;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;/*** @author 韩顺平* @version 1.0* 演示通过反射调用方法*/public class ReflecAccessMethod {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {//1. 得到Boss类对应的Class对象Class<?> bossCls = Class.forName("com.hspedu.reflection.Boss");//2. 创建对象Object o = bossCls.newInstance();//3. 调用public的hi方法//Method hi = bossCls.getMethod("hi", String.class);//OK//3.1 得到hi方法对象Method hi = bossCls.getDeclaredMethod("hi", String.class);//OK//3.2 调用hi.invoke(o, "韩顺平教育~");//4. 调用private static 方法//4.1 得到 say 方法对象Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);//4.2 因为say方法是private, 所以需要暴破,原理和前面讲的构造器和属性一样say.setAccessible(true);System.out.println(say.invoke(o, 100, "张三", '男'));//4.3 因为say方法是static的,还可以这样调用 ,可以传入nullSystem.out.println(say.invoke(null, 200, "李四", '女'));//5. 在反射中,如果方法有返回值,统一返回Object , 但是他运行类型和方法定义的返回类型一致Object reVal = say.invoke(null, 300, "王五", '男');System.out.println("reVal 的运行类型=" + reVal.getClass());//String//在演示一个返回的案例Method m1 = bossCls.getDeclaredMethod("m1");Object reVal2 = m1.invoke(o);System.out.println("reVal2的运行类型=" + reVal2.getClass());//Monster}}class Monster {}class Boss {//类public int age;private static String name;public Boss() {//构造器}public Monster m1() {return new Monster();}private static String say(int n, String s, char c) {//静态方法return n + " " + s + " " + c;}public void hi(String s) {//普通public方法System.out.println("hi " + s);}}