1. 什么是反射?
反射允许对封装类的字段,方法和构造函数的信息进行编程访问。
反射允许对成员变量,成员方法和构造方法的信息进行编程访问
2. 获取class对象的三种方式
- Class.forName(“全类名”)(最常用)
- 类名.class
- 对象.getClass()
代码示例
package com.bobo.reflect;
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
//第一种方式
//全类名:包名+类名
//最为常用
Class clazz = Class.forName("com.bobo.reflect.Student");
System.out.println(clazz);//class com.bobo.reflect.Student
//第二种方式
//一般当做参数进行传递(例如在锁中的应用)
Class clazz1 = Student.class;
System.out.println(clazz1);
//第三种方式
//有了这个类的对象才使用
Student s = new Student();
Class clazz2 = s.getClass();
System.out.println(clazz2);
System.out.println(clazz == clazz1);//true
System.out.println(clazz1 == clazz2);//true
}
}
3. 获取构造方法
方法名 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 获得所有的构造(只能public修饰) |
Constructor<?>[] getDeclaredConstructors() | 获得所有的构造(包含private修饰) |
Constructor getConstructor(Class<?>… parameterTypes) | 获取指定构造(只能public修饰) |
Constructor getDeclaredConstructor(Class<?>… parameterTypes) | 获取指定构造(包含private修饰) |
代码示例:
package com.bobo.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
public class Test1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//获取class字节码文件对象
Class clazz = Class.forName("com.bobo.reflect.Student");
//获取构造方法
Constructor[] cons = clazz.getConstructors();
for (Constructor con : cons) {
System.out.println(con);
}
System.out.println("=================");
Constructor[] cons1 = clazz.getDeclaredConstructors();
for (Constructor con : cons1) {
System.out.println(con);
}
System.out.println("=================");
Constructor con2 = clazz.getConstructor();//获取到public修饰的无参构造
System.out.println(con2);
Constructor con3 = clazz.getConstructor(String.class);//获取到public修饰的参数为String的构造方法
System.out.println(con3);
System.out.println("=================");
Constructor con4 = clazz.getDeclaredConstructor(String.class, int.class);
System.out.println(con4);
System.out.println("=================");
int modifiers = con4.getModifiers();//获取权限修饰符,以常量展示
System.out.println(modifiers);
System.out.println("=================");
Parameter[] parameters = con4.getParameters();//获取该构造方法参数
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
System.out.println("=================");
//暴力反射:临时取消权限校验
//con4权限修饰符为private
con4.setAccessible(true);
Student stu = (Student) con4.newInstance("zahngsan", 23);
System.out.println(stu);
}
}
package com.bobo.reflect;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name) {
this.name = name;
}
protected Student(int age){
this.age = age;
}
private Student(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
4. 获取成员变量
方法名:
方法名 | 说明 |
---|---|
Field[] getFields() | 返回所有成员变量对象的数组(只能拿public的) |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组,存在就能拿到 |
Field getField(String name) | 返回单个成员变量对象(只能拿public的) |
Field getDeclaredField(String name) | 返回单个成员变量对象,存在就能拿到 |
代码实例:
package com.bobo.reflect1;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//获取class字节码文件
Class clazz = Class.forName("com.bobo.reflect1.Student");
//获取成员变量
Field[] fields = clazz.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("==============");
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("==============");
//获取单个成员变量
Field gender = clazz.getField("gender");
System.out.println(gender);
System.out.println("==============");
Field name = clazz.getDeclaredField("name");
System.out.println(name);
System.out.println("==============");
//获取权限修饰符
int modifiers = name.getModifiers();
System.out.println(modifiers);
System.out.println("==============");
//获取成员变量名字
String n = name.getName();
System.out.println(n);
System.out.println("==============");
//获取成员变量数据类型
Class<?> type = name.getType();
System.out.println(type);
System.out.println("==============");
//获取成员变量记录的值
Student student = new Student("zahngsan",23,"men");
name.setAccessible(true);
String value = (String) name.get(student);
System.out.println(value);
System.out.println("==============");
//修改参数中student对象的 name 值
name.set(student,"lisi");
System.out.println(student);
System.out.println("==============");
}
}
package com.bobo.reflect1;
public class Student {
private String name;
private int age;
public String gender;
public Student() {
}
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + ", gender = " + gender + "}";
}
}
5. 获取成员方法
方法名 | 说明 |
---|---|
Method[] getMethods() | 返回所有成员方法对象的数组(只能拿public的) |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,存在就能拿到 |
Method getMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象(只能拿public的) |
Method getDeclaredMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象,存在就能拿到 |
代码实例:
package com.bobo.reflect2;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//获取class字节码文件
Class clazz = Class.forName("com.bobo.reflect2.Student");
//获取里面所有public修饰的方法(包括父类中的所有公共方法)
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("===============");
//获取里面所有方法(不能获取父类的方法)
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("===============");
//获取指定的单一方法
Method eat = clazz.getDeclaredMethod("eat", String.class, int.class);
System.out.println(eat);
System.out.println("===============");
//获取方法的修饰符
int modifiers = eat.getModifiers();
System.out.println(modifiers);
System.out.println("===============");
//获取方法的名字
String name = eat.getName();
System.out.println(name);
System.out.println("===============");
//获取方法的形参
int parameterCount = eat.getParameterCount();
System.out.println(parameterCount);
System.out.println("===============");
Parameter[] parameters = eat.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
System.out.println("===============");
//获取方法抛出的异常
Class[] exceptionTypes = eat.getExceptionTypes();
for (Class exceptionType : exceptionTypes) {
System.out.println(exceptionType);
}
System.out.println("===============");
//运行方法
Student student = new Student();
eat.setAccessible(true);
//参数一:方法调用者
//参数二、三:该方法的参数
eat.invoke(student,"hanbao",12);
System.out.println("===============");
}
}
package com.bobo.reflect2;
import java.io.IOException;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void sleep() {
System.out.println("sleep");
}
private void eat(String something) {
System.out.println("eat" + something);
}
private void eat(String something,int a) throws IOException,NullPointerException {
System.out.println("eat" + something + a);
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
6. 反射的作用
- 获取一个类里面所有的信息,获取到了之后,再执行其他的业务逻辑
- 结合配置文件,动态的创建对象并调用方法