反射(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对象的方式四: 包装类.TYPE
Class<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. 获取Class
Class<?> 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); // 0
ageField.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);
}
}
}