什么是反射
反射(Reflection) 是一种在运行时(Runtime) 动态分析、检查和操作类、方法、字段、构造方法等程序结构的能力。
通俗来说,通过Java中的反射机制,可以程序运行期间,在不知道具体类或者对象的情况下,通过该类的字节码对象,动态加载类、创建对象、调用方法、访问字段,甚至是修改私有成员。
反射提供了一种全新的创建对象,调用方法,访问成员变量的形式。
反射的起点是字节码对象。
获取字节码文件对象的几种方式
- 对象.getClass()
- 类名.class
- Class.forName(String className) 全限定名
- ClassLoader里的loadClass(String className)
注意:
无论通过什么方式获取的字节码文件对象 都是同一个
Demo
package _23reflect.com.cskaoyan._02cls;
/*
获取字节码文件对象的几种方式
*/
public class Demo {
public static void main(String[] args) throws ClassNotFoundException {
// 对象.getClass
A a = new A();
Class<? extends A> c1 = a.getClass();
// 类名.class
Class<A> c2 = A.class;
System.out.println(c1 == c2);
// Class.forName(全限定名)
Class<?> c3 = Class.forName("_23reflect.com.cskaoyan._02cls.A");
System.out.println(c1 == c3);
// ClassLoader.loadClass(String className)
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
Class<?> c4 = systemClassLoader.loadClass("_23reflect.com.cskaoyan._02cls.A");
System.out.println(c1 == c4);
}
}
class A{
}
关于Class
Class 类的实例表示正在运行的 Java 应用程序中的类和接口
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
通过反射获取构造方法(Constructor)
通过反射获取所有构造方法
// 获取所有的public修饰的构造方法
Constructor[] getConstructors()
// 获取所有的构造方法,包括私有构造方法
Constructor[] getDeclaredConstructors()
获取指定构造方法
Constructor<T> getConstructor(Class<?>... parameterTypes)
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
使用Constructor创建对象
Person p = new Person("zs",20,true)
newInstance(参数列表)
暴力破解
setAccessible(true)
package _23reflect.com.cskaoyan._04api;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ConstructorTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// 反射技术的起点 获取字节码文件对象
Class<?> stuCls = Class.forName("_23reflect.com.cskaoyan.bean.Person");
System.out.println("获取所有的public的构造方法----");
// Constructor[] getConstructors()
Constructor<?>[] constructors = stuCls.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
System.out.println("获取所有的构造方法----");
//Constructor[] getDeclaredConstructors()
Constructor<?>[] declaredConstructors = stuCls.getDeclaredConstructors();
for (Constructor<?> constructor : declaredConstructors) {
System.out.println(constructor);
}
System.out.println("获取指定的public的构造方法----");
// Constructor<T> getConstructor(Class<?>... parameterTypes)
Constructor<?> constructor = stuCls.getConstructor(String.class, int.class, boolean.class);
//Constructor<?> constructor = stuCls.getConstructor(String.class, int.class);
// java.lang.NoSuchMethodException
System.out.println(constructor);
System.out.println("获取指定的构造方法----");
//Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
Constructor<?> declaredConstructor = stuCls.getDeclaredConstructor(String.class, int.class);
System.out.println(declaredConstructor);
// 使用构造方法对象创建对象
// newInstance
Object o = constructor.newInstance("zs", 20, true);
System.out.println(o);
// java.lang.IllegalAccessException
// setAccessible(true) 忽略java语法检查
declaredConstructor.setAccessible(true);
Object o1 = declaredConstructor.newInstance("ls", 21);
System.out.println(o1);
}
}
通过反射获取成员变量(Field)
通过反射获取所有成员变量
// 获取所有public 修饰的成员变量,包括继承自父类中的成员
Field[] getFields()
// 获取所有在该类中定义的成员,包括私有成员
Field[] getDeclaredFields()
获取指定成员变量
Field getField(String name)
Field getDeclaredField(String name)
通过Field读写对象的成员变量(可暴力破解)
Object get(Object obj):获取值,传入对象
void set(Object obj, Object value):赋值,传入对象
package _23reflect.com.cskaoyan._04api;
import _23reflect.com.cskaoyan.bean.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/*
反射获取成员变量
*/
public class FieldTest {
public static void main(String[] args) throws Exception{
// 获取字节码文件对象
Class<?> personCls = Class.forName("_23reflect.com.cskaoyan.bean.Person");
System.out.println("获取所有的public的成员变量------");
// Field[] getFields()
Field[] fields = personCls.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("获取所有的成员变量------");
//Field[] getDeclaredFields()
Field[] declaredFields = personCls.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field);
}
System.out.println("获取指定的public的成员变量------");
// Field getField(String name)
Field nameField = personCls.getField("name");
System.out.println(nameField);
System.out.println("获取指定的成员变量------");
//Field getDeclaredField(String name)
Field ageField = personCls.getDeclaredField("age");
System.out.println(ageField);
// 给成员变量赋值 获取成员变量的值
//void set(Object obj, Object value):赋值,传入对象
Constructor<?> declaredConstructor = personCls.getDeclaredConstructor();
// 实例化对象
Object o = declaredConstructor.newInstance();
nameField.set(o, "zs");
System.out.println(o);
ageField.setAccessible(true);
ageField.set(o, 22);
System.out.println(o);
// Object get(Object obj):获取值,传入对象
Object o1 = nameField.get(o);
System.out.println(o1);
}
}
通过反射获取成员方法(Method)
获取所有成员方法
// 获取所有的public修饰的方法,包括继承的父类中的方法
Method[] getMethods();
// 获取所有在该类中定义的方法,包括私有方法,不包括父类中的方法
Method[] getDeclaredMethods()
获取指定的成员方法
Method getMethod(String name, Class<?>... parameterTypes)
Method getDeclaredMethod(String name, Class<?>... parameterTypes)
利用Method调用对象的方法
Object invoke(Object obj, Object... args)
package _23reflect.com.cskaoyan._04api;
import _23reflect.com.cskaoyan.bean.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* @description:
* @author: 景天
* @date: 2022/10/24 14:39
**/
/*
通过反射获取方法
*/
public class MethodTest {
public static void main(String[] args) throws Exception{
// 获取字节码文件对象
Class<?> personCls = Class.forName("_23reflect.com.cskaoyan.bean.Person");
System.out.println("获取所有的public的方法----");
// Method[] getMethods()
Method[] methods = personCls.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("获取所有的方法----");
//Method[] getDeclaredMethods()
Method[] declaredMethods = personCls.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method);
}
System.out.println("获取指定的public的方法----");
// Method getMethod(String name, Class<?>... parameterTypes)
Method eatMethod1 = personCls.getMethod("eat");
System.out.println(eatMethod1);
System.out.println("获取指定的方法----");
//Method getDeclaredMethod(String name, Class<?>... parameterTypes)
Method eatMethod2 = personCls.getDeclaredMethod("eat", String.class);
System.out.println(eatMethod2);
//Person p = new Person();
//p.eat();
// 反射调用方法
// Object invoke(Object obj, Object... args)
Constructor<?> declaredConstructor = personCls.getDeclaredConstructor();
Object o = declaredConstructor.newInstance();
Object invoke = eatMethod1.invoke(o);
System.out.println(invoke);
eatMethod2.setAccessible(true);
eatMethod2.invoke(o, "apple");
}
}
补充
其他API
package _23reflect.com.cskaoyan.bean;
/**
* @description:
* @author: 景天
* @date: 2022/10/24 11:31
**/
public class Person {
// 定义成员变量
public String name;
private int age;
boolean gender;
// 构造方法
public Person(String name, int age, boolean gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
private Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
// 定义成员方法
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
'}';
}
public String eat(){
System.out.println("eat food!");
return "吃了";
}
private void eat(String food){
System.out.println("eat " + food);
}
}
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class OtherApi {
public static void main(String[] args) throws Exception{
// 获取字节码文件对象
Class<?> c = Class.forName("_23reflect.com.cskaoyan.bean.Person");
//Class<?> c = Class.forName("java.io.OutputStream");
// 获取全限定类名
System.out.println(c.getName());
// 获取简单名称
System.out.println("c.getSimpleName() = " + c.getSimpleName());
// 获取父类
Class<?> superclass = c.getSuperclass();
System.out.println("superclass = " + superclass.getSimpleName());
// 获取实现的接口
Class<?>[] interfaces = c.getInterfaces();
for (Class<?> i : interfaces) {
System.out.println(i);
}
// 获取类加载器
ClassLoader classLoader = c.getClassLoader();
System.out.println("classLoader = " + classLoader);
// 获取name这个成员变量对象
Field nameField = c.getDeclaredField("name");
// 获取权限修饰符
int modifiers = nameField.getModifiers();
System.out.println(modifiers);
// static String toString(int mod)
// 返回描述指定修饰符中的访问修饰符标志的字符串。
String s = Modifier.toString(modifiers);
System.out.println("s = " + s);
// 获取eat(String s)方法对象
Method eatMethod = c.getDeclaredMethod("eat", String.class);
Class<?> returnType = eatMethod.getReturnType();
System.out.println("returnType = " + returnType);
Class<?>[] parameterTypes = eatMethod.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println(parameterType.getSimpleName());
}
}
}