Java反射是Java编程语言中的一个重要特性,它允许程序在运行时获取类的信息,操作对象的内部结构,甚至动态地创建和操作对象。反射机制使得Java程序具有了更高的灵活性和扩展性,可以在不修改代码的情况下实现一些动态的功能。
一、 获取Class对象
要使用反射机制,首先需要获取一个Class对象,它表示我们要操作的类。获取Class对象的方式如下:
(1)、类名.class。
(2)、包名+类名:Class.forName("全类名")。
(3)、对象名.getclass。
例:
package com.wedu.Reflect1;
public class Person {
public Integer id;
private String color;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
public class ReflectDemo1 {
//获取class对象的方式
public static void main(String[] args) throws ClassNotFoundException {
//类名.class
Class<Person> class1= Person.class;
System.out.println(class1);
//包名+类名
Class<?> class2 = Class.forName("com.wedu.Reflect1.Person");
System.out.println(class2);
//对象.getClass
Person person = new Person();
Class<? extends Person> class3 = person.getClass();
System.out.println(class3);
System.out.println(class1==class2);
System.out.println(class2==class3);
}
}
二、反射获取构造方法
1、方法介绍
Constructor<?>[] getConstructors() | 返回所有公共构造方法对象的数组 |
Constructor<?>[] getDeclaredConstructors() | 返回所有构造方法对象的数组 |
Constructor<T> getConstructor(Class<?>... parameterTypes) | 返回单个公共构造方法对象 |
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) | 返回单个构造方法对象 |
package com.wedu.Reflect1;
public class Student {
private String name;
private int age;
//共有的无参
public Student() {
}
//共有的有参构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
System.out.println("name的值为:"+name+"age的值为:"+age);
System.out.println("共有的有参构造方法");
}
//私有的有参构造方法
private Student(String name){
System.out.println("name的值为:"+name);
System.out.println("私有的有参构造方法");
}
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 study(){
System.out.println("学生在学习");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.wedu.Reflect1;
import java.lang.reflect.Constructor;
public class ReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//获取字节码对象
Class clazz = Class.forName("com.wedu.Reflect1.Student");
//返回所有的公共的构造方法的数组对象
Constructor[] constructors1= clazz.getConstructors();
for (Constructor constructor : constructors1) {
System.out.println(constructor);
}
//返回所有的构造方法的数组对象
Constructor[] constructors2 = clazz.getDeclaredConstructors();
for (Constructor constructor : constructors2) {
System.out.println(constructors2);
}
//返回单个公共构造方法对象
Constructor constructor1 = clazz.getConstructor();
System.out.println(constructor1);
Constructor constructor2 = clazz.getConstructor(String.class, int.class);
System.out.println(constructor2);
//返回单个构造方法的对象
Constructor constructor = clazz.getDeclaredConstructor(String.class);
System.out.println(constructor);
}
}
2、Constructor类用于创建对象的方法
方法名 | 说明 |
---|---|
T newInstance(Object...initargs) | 根据指定的构造方法创建对象 |
setAccessible(boolean flag) | 设置为true,表示取消访问检查 |
package com.wedu.Reflect1;
public class Student3 {
private String name;
private int age;
public Student3() {
}
public Student3(String name) {
this.name = name;
}
protected Student3(int age) {
this.age = age;
}
private Student3(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;
}
@Override
public String toString() {
return "Student3{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.wedu.Reflect1;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ReflectDemo3 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//获取class字节码文件对象
Class clazz = Class.forName("com.wedu.Reflect1.Student3");
//获取公共的构造方法
Constructor[] cons1 = clazz.getConstructors();
for (Constructor con : cons1) {
System.out.println(con);
}
System.out.println("---------------------------------------------------------------------");
//获取所有的构造方法
Constructor[] cons2 = clazz.getDeclaredConstructors();
for (Constructor con : cons2) {
System.out.println(con);
}
System.out.println("------------------------------------------------------------------------");
//获取单个构造方法
Constructor con1 = clazz.getDeclaredConstructor();
System.out.println(con1);
Constructor con2 = clazz.getDeclaredConstructor(String.class);
System.out.println(con2);
Constructor con3 = clazz.getDeclaredConstructor(int.class);
System.out.println(con3);
Constructor con4 = clazz.getDeclaredConstructor(String.class,int.class);
System.out.println(con4);
System.out.println("--------------------------------------------------------------------------");
con4.setAccessible(true);//表示临时取消权限校验
Student3 stu = (Student3) con4.newInstance("张三", 23);
System.out.println(stu);
}
}
三、反射获取成员属性
Field[] getFields() | 返回所有公共成员变量对象的数组 |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组 |
Field getField(String name) | 返回单个公共成员变量对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象 |
package com.wedu.Reflect1;
public class Student4 {
private String name;
private int age;
public String gender;
public Student4() {
}
public Student4(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;
}
@Override
public String toString() {
return "Student4{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
package com.wedu.Reflect1;
import java.lang.reflect.Field;
public class ReflectDemo4 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//获取字节码
Class clazz = Class.forName("com.wedu.Reflect1.Student4");
//获取所有的成员变量
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//获取单个的成员变量
Field name = clazz.getDeclaredField("name");
System.out.println(name);
//获取权限修饰符
int modifiers = name.getModifiers();
System.out.println(modifiers);
//获取成员变量的名字
String n = name.getName();
System.out.println(n);
//获取成员变量的数据类型
Class<?> type = name.getType();
System.out.println(type);
//获取成员变量记录的值
Student4 s=new Student4("zhangsan",23,"男");
name.setAccessible(true);//暴力反射
Object value = name.get(s);
System.out.println(value);
}
}
四、反射获取成员方法
Method[] getMethods() | 返回所有公共成员方法对象的数组,包括继承的 |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,不包括继承的 |
Method getMethod(String name, Class<?>... parameterTypes) | 返回单个公共成员方法对象 |
Method getDeclaredMethod(String name, Class<?>... parameterTypes) | 返回单个成员方法对象 |
package com.wedu.Reflect1;
import java.io.IOException;
public class Student5 {
private String name;
private int age;
public Student5() {
}
public Student5(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("睡觉");
}
private String eat(String something)throws IOException,NullPointerException {
System.out.println("在吃"+something);
return "好好吃";
}
private void eat(String something,int a){
System.out.println("在吃"+something);
}
@Override
public String toString() {
return "Student5{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.wedu.Reflect1;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectDemo5 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//获取字节码文件
Class clazz = Class.forName("com.wedu.Reflect1.Student5");
//获取所有的成员方法(包括父类中的所有公共方法)
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 m = clazz.getDeclaredMethod("eat", String.class);
System.out.println(m);
System.out.println("-------------------------------------------------------");
//获取方法的修饰符
int modifiers = m.getModifiers();
System.out.println(modifiers);
System.out.println("-------------------------------------------------------");
//获取方法的名字
String name = m.getName();
System.out.println(name);
System.out.println("-------------------------------------------------------");
//获取方法的形参
Class[] parameterTypes = m.getParameterTypes();
for (Class parameterType : parameterTypes) {
System.out.println(parameterType);
}
System.out.println("-------------------------------------------------------");
//获取方法的抛出的异常
Class[] exceptionTypes = m.getExceptionTypes();
for (Class exceptionType : exceptionTypes) {
System.out.println(exceptionType);
}
System.out.println("-------------------------------------------------------");
//运行方法
Student5 s=new Student5();
m.setAccessible(true);
//s表示方法的调用者,“蛋糕”表示在调用方法的时候传递的实际参数
String result = (String) m.invoke(s, "蛋糕");
System.out.println(result);
}
}
五、应用场景
Java反射机制有很多应用场景,例如:
1、动态代理:通过反射机制,我们可以动态地生成代理类,实现对方法的拦截和增强。
2、 插件化开发:通过反射机制,我们可以动态地加载和卸载插件,实现程序的扩展和定制。
3、ORM框架:通过反射机制,我们可以将Java对象和数据库表进行映射,实现对象的持久化和查询。
六、 总结
Java反射机制是Java编程语言中的一个重要特性,它允许程序在运行时获取类的信息,操作对象的内部结构,甚至动态地创建和操作对象。反射机制使得Java程序具有了更高的灵活性和扩展性,可以在不修改代码的情况下实现一些动态的功能。本文通过实例介绍了Java反射的使用方法和应用场景,希望对你有所帮助。