一、反射的概念
在运行时,对任意一个类都可以获取其属性 方法构造等(类结构);对任意对象都能对属性进行赋值,对方法进行执行,可以操作类。这种动态获取类信息以及动态对类进行操作的机制称之为反射机制(reflect)
二、反射相关类
类名 | 用途 |
Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
Field类 | 代表类的成员变量(成员变量也称为类的属性) |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造方法 |
Annotation类 | 代表注解 |
2.1 Class类
Class代表类的实体,在运行的Java应用程序中表示类和接口。在这个类中提供了很多有用的方法,这里对他们简单的分类介绍。
2.1.1 获得Class相关的方法
1)Class.forName();
Class clazz1=Class.forName("com.aaa.getclass.Person");
对象.getClass();
2)Person p= new Person();
p.getClass()
3)类名.class;
Class clazz2=Person.class;
通过反射实例化:
Class对象.newInstance()
通过 Constructor 对象的 newInstance() 方法
创建一个人类与学生类进行演示
package com.aaa.reflectDemo.reflect;
import com.aaa.reflectDemo.ann.MyAnn;
import java.io.Serializable;
/**
* @author :caicai
* @date :Created in 2022/6/14 8:56
* @description:Person类
* @modified By:
* @version:
*/
@MyAnn(name = "xxx")
public class Person implements Serializable {
@MyAnn
private int id;
public String name;
public Person() {
}
public Person(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private double jiSuan(int a,int b,String fuhao){
double c=0.0;
switch (fuhao){
case "+":
c = a+b;
break;
case "-":
c = a-b;
break;
case "*":
c = a*b;
break;
case "/":
c = a*1.0/b;
break;
default:
System.out.println("不支持该方法");
}
return c;
}
public void introduce(String name){
System.out.println("大家好我叫:"+name);
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
package com.aaa.reflectDemo.reflect;
/**
* @author :caicai
* @date :Created in 2022/6/14 8:57
* @description:学生类
* @modified By:
* @version:
*/
public class Student extends Person{
private int stuId;
public Student() {
}
public Student(int stuId) {
this.stuId = stuId;
}
public Student(int id, String name, int stuId) {
super(id, name);
this.stuId = stuId;
}
public int getStuId() {
return stuId;
}
public void setStuId(int stuId) {
this.stuId = stuId;
}
public void testDemo(){
System.out.println("hahah");
}
}
获得Class相关的方法相关代码演示
package com.aaa.reflectDemo.reflect;
/**
* @author :caicai
* @date :Created in 2022/8/15 16:25
* @description:
* @modified By:
* @version:
*/
public class Test {
public static void main(String[] args) {
// 获得Class相关的方法
// 1、通过类名(全路径名)获取class对象com.aaa.refelctDemo.reflect.Student
try {
Class<?> aClass = Class.forName("com.aaa.reflectDemo.reflect.Student");
System.out.println(aClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//2、通过对象的getClass方法获取
Person student = new Student();
// 泛型上限 小于等于person
Class<? extends Person> aClass = student.getClass();
System.out.println(aClass);
//3、通过.class的方式获取class对象
Class<Student> aClass1 = Student.class;
System.out.println(aClass1);
}
}
结果打印
2.1.2 获取类的基本信息的方法
getName() | 获得类的完整路径名字 |
newInstance() | 创建类的实例 |
getPackage() | 获得类的包 |
getSimpleName() | 获得类的名字 |
getSuperclass() | 获得当前类继承的父类的名字 |
getAnnotation() | 获取类上的注解 |
getInterfaces() | 获得当前类实现的类或是接口 |
package com.aaa.reflectDemo.reflect;
import java.lang.annotation.Annotation;
public class Test {
public static void main(String[] args) {
// 获取类的基本信息的方法
Class<Person> clazz = Person.class;
System.out.println("==============获取类的基本信息·===============");
String clazzName = clazz.getName(); // 获得类的完整路径名字
String packageName = clazz.getPackage().getName(); // 获得类的包
String simpleName = clazz.getSimpleName(); // 获得类的名字
System.out.println(clazzName);
System.out.println(packageName);
System.out.println(simpleName);
// 通过反射实例化 Constructor 对象的 newInstance() 方法
System.out.println("==============反射实例化=====================");
try {
Person person = clazz.newInstance(); //通过反射创建类的实例 调用的是无参的构造器
person.setId(11);
person.setName("反射实例化");
System.out.println(person.toString());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// 泛型下限,大于等于person
System.out.println("===========获得当前类继承的父类的名字===============");
Class<? super Person> superclass = clazz.getSuperclass(); // 获得当前类继承的父类的名字
System.out.println(superclass);
//获取注解
System.out.println("===========获获取类上的注解=======================");
Annotation[] annotations = clazz.getAnnotations();// 获取类上的注解
System.out.println(annotations.length);
for (Annotation annotation : annotations) {
System.out.println(annotation.toString());
}
//获取接口
System.out.println("===========获得当前类实现的类或是接口===============");
Class<?>[] interfaces = clazz.getInterfaces(); //获得当前类实现的类或是接口
System.out.println(interfaces.length);
for (Class<?> anInterface : interfaces) {
System.out.println(anInterface.toString());
}
}
}
结果打印:
2.2 Field类
2.2.1 获得类中属性相关的方法
方法 | 用途 |
getField(String name) | 获得某个公有的属性对象 |
getFields() | 获得所有公有的属性对象 |
getDeclaredField(String name) | 获得某个私有属性对象 |
getDeclaredFields() | 获得所有属性对象 |
Field类中的方法
方法 | 用途 |
equals(Object obj) | 属性与obj相等则返回true |
get(Object obj) | 获得obj中对应的属性值 |
set(Object obj, Object value) | 设置obj中对应属性值 |
package com.aaa.reflectDemo.reflect;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
// Field类 获得类中属性相关的方法
System.out.println("==========获得类中属性相关的方法=============");
Class<Person> clazz = Person.class;
// 获取公有属性
Field field = clazz.getField("name");
System.out.println(field);
Field[] fields = clazz.getFields();
for (Field field1 : fields) {
System.out.println(field1);
}
//获取私有属性(可以获取共有的和私有的)
System.out.println("-------------------私有属性-----------------");
Field id = clazz.getDeclaredField("id");
System.out.println(id);
Field[] fields1 = clazz.getDeclaredFields();
for (Field field1 : fields1) {
System.out.println(field1);
}
// Field类中的方法 获得person中对应的属性值
System.out.println("----------公有/私有属性取值赋值------------");
Person person = new Person(1,"张三");
Field name = clazz.getField("name");
Field ids = clazz.getDeclaredField("id");
ids.setAccessible(true); // 私有取值时先放行
System.out.println("姓名:"+name+"\t 用户id:"+ids);
// 取值
System.out.println("姓名:"+name.get(person)+"\t id为:"+ids.get(person));
System.out.println("反射赋值在以前"+person.toString());
System.out.println("----------------赋值---------------------");
name.set(person,"李四"); // 共有属性
id.setAccessible(true); // 私有属性 需要现先予临时赋权限 才可以修改值
id.set(person,2);
System.out.println("反射赋值之后"+person.toString());
}
}
结果打印
2.3 Method类
2.3.1 CLASS获得类中方法相关的方法
方法 | 用途 |
getMethod(String name, Class...<?> parameterTypes) | 根据方法名和参数类型获取方法对象 |
getMethods() | 获得该类所有公有的方法,不包含构造方法 |
getDeclaredMethod(String name, Class...<?> parameterTypes) | 获得该类某个方法 |
getDeclaredMethods() | 获得该类所有方法,不包含父类 |
package com.aaa.reflectDemo.reflect;
import java.lang.reflect.Method;
public class Test1 {
public static void main(String[] args) throws NoSuchMethodException {
// Method类 CLASS获得类中方法相关的方法
// getMethod(String name, Class...<?> parameterTypes) 根据方法名和参数类型获取方法对象
System.out.println("==============获取类中的方法=================");
Class<Person> clazz = Person.class;
System.out.println("------------获取单一方法----------");
//获取单的某个方法
Method introduce2 = clazz.getMethod("introduce", String.class);
System.out.println(introduce2.toString());
System.out.println("-----------------获取公有方法--------------------");
// 获取所有公有方法 包含继承的 不包含有参无参构造方法
Method[] methods = clazz.getMethods();
System.out.println(methods.length);
for (Method method : methods) {
System.out.println(method.toString());
}
System.out.println("-----------------获取私有方法--------------------");
//获取所有的私有方法包含公有的,不包含继承的
Method[] methods2 = clazz.getDeclaredMethods();
System.out.println(methods2.length);
for (Method method : methods2) {
System.out.println(method.toString());
}
}
}
结果打印:
2.4 Constructor类
获得类中构造器相关的方法
方法 | 用途 |
getConstructor(Class...<?> parameterTypes) | 获得该类中与参数类型匹配的公有构造方法 |
getConstructors() | 获得该类的所有公有构造方法 |
getDeclaredConstructor(Class...<?> parameterTypes) | 获得该类中与参数类型匹配的构造方法 |
getDeclaredConstructors() | 获得该类所有构造方法 |
package com.aaa.reflectDemo.reflect;
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) throws NoSuchMethodException {
// Constructor类
//获取单个参数的构造器
Class<Person> clazz = Person.class;
Constructor<Person> constructor = clazz.getConstructor();
// Constructor<Person> constructor = clazz.getConstructor(int.class,String.class);
System.out.println(constructor.toString());
}
}
结果打印
2.5 Annotation类
创建一个自己的注解
package com.aaa.reflectDemo.ann;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 我的注解
* 元(meta)注解@Retention 指定注解生效的生命周期
* 元注解@Target 指定注解标注的位置,
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface MyAnn {
String name() default "";
}
在java类上加上自定义注解,使用反射获取该注解
package com.aaa.reflectDemo.reflect;
import com.aaa.reflectDemo.ann.MyAnn;
public class Test1 {
public static void main(String[] args) throws NoSuchMethodException {
// Annotation类 使用反射获取该注解
//获取单个注解
Class<Person> clazz = Person.class;
MyAnn annotation = clazz.getAnnotation(MyAnn.class);
System.out.println(annotation);
//获取注解中的值 如果使用反射获取注解信息,注解必须@Retention(RetentionPolicy.RUNTIME)
System.out.println(annotation.name());
}
}
结果打印