反射(reflect)和注解
无反射无框架。
反射的介绍
package com.powernode.p2;public class Demo01 {public static void main(String[] args) {// 正向创建 --- 静态的 --- 指腹为婚/** 之所以叫做静态的, 是因为我们创建对象的时候类已经固定了* 也就是这句代码创建的就是Student的对象。不会是其他类的对象了*/Student student = new Student("张三",20);System.out.println(student);System.out.println("-----------------------------------");// 使用反射 --- 动态的/** 之所以叫做动态的是因为,我们创建对象的类没有固定,可以是任意的。**/try {Class<?> aClass = Class.forName(args[0]);Object obj = aClass.newInstance();System.out.println(obj);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();}}}
Class类
public final class Class<T> extends Object implements Serializable, GenericDeclaration, Type, AnnotatedElement
- 类型参数:
T- 由此Class对象建模的类的类型。例如,String.class的类型是Class。如果将被建模的类未知,则使用Class。
Class类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该Class对象。基本的 Java 类型(boolean、byte、char、short、int、long、float和double)和关键字void也表示为Class对象。
Class没有公共构造方法。Class对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass方法自动构造的。
获取Class对象的四种方式
package com.powernode.p2;/*** 获取Class对象**/public class Demo02 {public static void main(String[] args) {// FQCN(Fully Qualified Class Name) 全限定类名 包名.类名// 获取Class对象的方式一:Class.forName(String FQCN); --- 推荐使用,好处就是解耦try {Class<?> aClass = Class.forName("com.powernode.p2.Student");System.out.println(aClass);System.out.println(aClass.getName());} catch (ClassNotFoundException e) {e.printStackTrace();}System.out.println("--------------------------------");// 获取Class对象的方式二:数据类型.class --- 作为参数传递的时候比较常用Class<Student> studentClass = Student.class;System.out.println(studentClass);System.out.println(studentClass.getName());System.out.println(int.class);System.out.println(boolean.class);System.out.println(int[][].class);System.out.println(void.class);System.out.println("--------------------------------");// 获取Class对象的方式三:对象.getClass()Student student = new Student();Class<? extends Student> aClass = student.getClass();System.out.println(aClass);System.out.println(aClass.getName());System.out.println("--------------------------------");// 获取Class对象的方式四: 包装类.TYPEClass<Integer> integerClass = Integer.TYPE;System.out.println(integerClass);Class<Double> doubleClass = Double.TYPE;System.out.println(doubleClass);Class<Character> characterClass = Character.TYPE;System.out.println(characterClass);}}
使用反射获取包信息
package com.powernode.p2;/*** 使用反射获取包的信息** 反射机制就是将类的各个组成部分(属性,方法,构造器)封装为其它对象。** 使用反射获取包的信息,会将封装成Package对象**/public class PackageDemo {public static void main(String[] args) {try {// 1. 获取ClassClass<?> aClass = Class.forName("com.powernode.p2.Student");// 2. 拿到Class后,使用反射你就可以为所欲为Package aPackage = aClass.getPackage();System.out.println(aPackage);System.out.println(aPackage.getName());} catch (ClassNotFoundException e) {e.printStackTrace();}}}
使用反射获取类信息
package com.powernode.p2;import java.lang.reflect.Modifier;/*** 使用反射获取类信息**/public class ClassDemo01 {public static void main(String[] args) {try {// Class.forName()得到的就是类的信息了Class<?> aClass = Class.forName("com.powernode.p2.Student");System.out.println(aClass.getName());// 获取类的修饰符信息int modifiers = aClass.getModifiers();System.out.println(modifiers); // 1 == public// 判断类是不是public修饰的System.out.println(Modifier.isPublic(modifiers));// 获取继承的父类Class<?> superclass = aClass.getSuperclass();System.out.println(superclass.getName());// 获取实现的接口// 父类实现的接口,子类是没有实现的Class<?>[] interfaces = aClass.getInterfaces();for (Class<?> anInterface : interfaces) {System.out.println(anInterface.getName());}} catch (ClassNotFoundException e) {e.printStackTrace();}}}
使用反射通过Class创建对象
Class<?> aClass = Class.forName("com.powernode.p2.Student");System.out.println(aClass.getName());/** 使用反射通过Class创建对象* aClass.newInstance()是通过无参构造创建对象* jdk9开始该方法被弃用了*/Object obj = aClass.newInstance();System.out.println(obj);
使用反射获取字段
package com.powernode.p2;import java.lang.reflect.Field;/*** 使用反射获取字段:* javabean中的成员变量也叫作字段Field** 反射机制就是将类的各个组成部分(属性,方法,构造器)封装为其它对象。* 反射就会将成员变量信息封装成Field对象***/public class FieldDemo01 {public static void main(String[] args) {Class<Student> studentClass = Student.class;try {// 获取指定的public字段// getField()可以获取本类定义的字段或者是继承的字段Field nameField = studentClass.getField("name");System.out.println(nameField);System.out.println(nameField.getName());System.out.println("-----------------------------");// 获取本类定义的或继承的所有public字段Field[] fields = studentClass.getFields();for (Field field : fields) {System.out.println("field= " + field);}System.out.println("-----------------------------");/** Declared 已声明过的。* 1. 本类中定义的才叫做声明。* 2. Declared可以获取任意访问权限的**/Field ageField = studentClass.getDeclaredField("age");System.out.println(ageField);System.out.println(ageField.getName());// 获取字段的访问权限System.out.println(ageField.getModifiers());System.out.println("-----------------------------");Field[] declaredFields = studentClass.getDeclaredFields();for (Field declaredField : declaredFields) {System.out.println("declaredField= "+ declaredField);}} catch (NoSuchFieldException e) {e.printStackTrace();}}}
使用反射给字段赋值和取值
package com.powernode.p2;import java.lang.reflect.Field;/*** 使用反射给字段赋值和取值*/public class FieldDemo02 {public static void main(String[] args) {Class<Student> studentClass = Student.class;try {// 获取字段对象Field nameField = studentClass.getField("name");// 取值/** get(Object obj)中的参数obi表示获取哪一个对象的字段*/Student student = studentClass.newInstance();Object value = nameField.get(student);System.out.println(value); // null// 赋值/** set(Object obj, Object value)* 第一个参数表示给哪个对象的字段赋值* 第二参数表示给字段赋什么值*/nameField.set(student,"李四");value = nameField.get(student);System.out.println(value); // 李四System.out.println("------------------------------");// 给private int age字段取值和赋值Field ageField = studentClass.getDeclaredField("age");// 暴力访问// 私有的字段不论是取值还是赋值都需要设置暴力访问// 设置为true表示反射对象在使用时忽略Java语言访问检查// ageField.setAccessible(true);Object ageValue = ageField.get(student);System.out.println(ageValue); // 0ageField.set(student,23);ageValue = ageField.get(student);System.out.println(ageValue); // 23} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();}}}
使用反射获取构造信息
package com.powernode.p2;import java.lang.reflect.Constructor;/*** 使用反射获取构造信息** 反射机制就是将类的各个组成部分(属性,方法,构造器)封装为其它对象。** 反射会将构造函数封装成Constructor对象***/public class ConstructorDemo01 {public static void main(String[] args) {Class<Student> studentClass = Student.class;/** getConstructor(Class<?>... parameterTypes)* 参数表示是的构造的参数类型的Class**/try {// 获取public的无参构造Constructor<Student> constructor = studentClass.getConstructor();System.out.println(constructor);System.out.println(constructor.getName());System.out.println("--------------------");// 获取public的带参构造Constructor<Student> constructor1 = studentClass.getConstructor(String.class,int.class);System.out.println(constructor1);System.out.println(constructor1.getName());System.out.println("--------------------");Constructor<?>[] constructors = studentClass.getConstructors();for (Constructor<?> constructor2 : constructors) {System.out.println("constructor2= " + constructor2);}System.out.println("--------------------");// 获取声明过的指定构造函数Constructor<Student> declaredConstructor = studentClass.getDeclaredConstructor(String.class);System.out.println(declaredConstructor);System.out.println("--------------------");// 获取声明过的所有构造函数Constructor<?>[] declaredConstructors = studentClass.getDeclaredConstructors();for (Constructor<?> declaredConstructor1 : declaredConstructors) {System.out.println("declaredConstructor1= " + declaredConstructor1);}} catch (NoSuchMethodException e) {e.printStackTrace();}}}
使用反射通过构造创建对象
package com.powernode.p2;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;/*** 使用反射通过构造创建对象**/public class ConstructorDemo02 {public static void main(String[] args) {Class<Student> studentClass = Student.class;try {Constructor<Student> constructor = studentClass.getConstructor();// 使用构造创建对象/** newInstance(Object ... initargs)* 参数表示使用构造创建对象的时候传入的实际参数**/Student student = constructor.newInstance();System.out.println(student);System.out.println("-------------------------------");// public Student(String name, int age)Constructor<Student> constructor1 = studentClass.getConstructor(String.class, int.class);Student zhangsan = constructor1.newInstance("张三", 22);System.out.println(zhangsan);System.out.println("---------------------------");// private Student(String name)Constructor<Student> declaredConstructor = studentClass.getDeclaredConstructor(String.class);declaredConstructor.setAccessible(true);Student lisi = declaredConstructor.newInstance("李四");System.out.println(lisi);} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}}
使用反射获取方法信息
package com.powernode.p2;import java.lang.reflect.Method;/*** 使用反射获取方法信息** 反射机制就是将类的各个组成部分(属性,方法,构造器)封装为其它对象。** 反射将方法的信息封装成Method对象***/public class MethodDemo01 {public static void main(String[] args) {try {Class<?> aClass = Class.forName("com.powernode.p2.Student");/** 获取指定的public方法,可以获取本类声明的,也可以获取继承父类的方法* getMethod(String name, Class<?>... parameterTypes)* 第一个参数表示方法的名字* 第二个参数表示方法形参类型的Class*/Method setName = aClass.getMethod("setName", String.class);System.out.println(setName);System.out.println("--------------------");// 获取本类及父类的所有public方法Method[] methods = aClass.getMethods();for (Method method : methods) {System.out.println("method= " + method);}System.out.println("--------------------");Method study = aClass.getDeclaredMethod("study");System.out.println(study);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();}}}
使用反射执行方法
package com.powernode.p2;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;/*** 使用反射执行方法**/public class MethodDemo02 {public static void main(String[] args) {Class<Student> studentClass = Student.class;try {Method eatMethod = studentClass.getDeclaredMethod("eat", String.class);// 调用方法/** Object invoke(Object obj, Object... args)* 第一参数表示执行哪一个对象的方法* 第二参数表示调用方法传入的实参** 返回值表示调用方法后方法的返回值* void 返回就是null**/eatMethod.setAccessible(true);Object returnValue = eatMethod.invoke(studentClass.newInstance(), "狗粮");System.out.println(returnValue);} catch (NoSuchMethodException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}}
使用反射获取内部类 — 扩展
package com.powernode.p2;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class InnerClassDemo {public static void main(String[] args) throws Exception{// test01();test02();}/** 演示成员内部类*/private static void test02() throws Exception {Class<Student> studentClass = Student.class;// 获取内部类Class<?>[] classes = studentClass.getClasses();for (Class<?> aClass : classes) {// aClass == Student$Inner// public Student$Inner(Student this$0) {}Constructor<?> constructor = aClass.getDeclaredConstructor(studentClass);Object innerObj = constructor.newInstance(studentClass.newInstance());// 调用内部类的方法Method runMethod = aClass.getDeclaredMethod("run");Object returnValue = runMethod.invoke(innerObj);System.out.println(returnValue);System.out.println("--------------------------");Field[] declaredFields = aClass.getDeclaredFields();for (Field declaredField : declaredFields) {System.out.println(declaredField);}}}/** 演示静态内部类*/private static void test01() throws Exception{Class<Student> studentClass = Student.class;// 获取内部类Class<?>[] classes = studentClass.getClasses();for (Class<?> aClass : classes) {// 调用内部类的方法Method runMethod = aClass.getDeclaredMethod("run");Object returnValue = runMethod.invoke(aClass.newInstance());System.out.println(returnValue);}}}
