目录
简介
1.定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意一个方法和属性; 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射机制中,一个类的属性,方法,构造方法,以及注释 都有与之对应的类对其进行描述,反射的核心思想就是把原有类的属性、方法、构造方法、注释乃至包命用一个又一个的类去拆解。
Class类
- final类。
- 运行中的类、接口是Class类的实例。
- 枚举是一种类、注解是一种接口、数组将被映射成一个Class类对象,具有相同元素类型与维度的数组将共享该对象。
- boolean, byte, char, short, int, long, float, and double,void 也是Class的实例对象。
- Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。
反射--获取Class对象的三种方式:
(别说创建Class对象、因为Class类的对象早就在内存中存在了,我们所要做的就是拿到这些对象直接使用)
package com.knowledge.system.java_system.reflection_system.bok_instance;
public class Student {
private Integer age;
private String name;
private String address;
private boolean sex;
public Student() {
System.out.println("公有无参构造函数");
}
private Student(Integer age) {
this.age = age;
System.out.println("私有一个参数构造函数");
}
protected Student(String name) {
this.name = name;
System.out.println("受保护一个参数构造函数");
}
public Student(boolean sex) {
this.sex = sex;
System.out.println("公有一个参数构造函数");
}
public Student(Integer age, String name, String address, boolean sex) {
this.age = age;
this.name = name;
this.address = address;
this.sex = sex;
}
public void testFun1(String msg){
System.out.println(msg);
}
public void testFun2(String msg){
System.out.println(msg);
}
public void testFun3(String msg){
System.out.println(msg);
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public boolean isSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
public static void main(String[] args) {
System.out.println("main 方法执行了。");
}
public static void testMain(String msg){
System.out.println("static 方法执行了,入参"+msg);
}
}
package com.knowledge.system.java_system.reflection_system.bok_instance;
import com.alibaba.fastjson.JSON;
import lombok.SneakyThrows;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* @program: demo-pom
* @description:
* @author: bo.hu
* @create: 2020-03-05 16:59
**/
public class ReflectionTest {
@Test
public void testGetClassObject(){
Student student=new Student();
Class clz=student.getClass();//对象角度---不常用,对象都有了还反射干啥
Class clz2=Student.class;//类角度---业务开发中常用(但要导包,依赖太强,不导包编译会出问题)
Class clz3=null;//静态方法角度---常用(全路径名可以通过配置文件搞进去)
try {
clz3=Class.forName("com.knowledge.system.java_system.reflection_system.bok_instance.Student");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(clz.getName());
System.out.println(JSON.toJSONString(clz3.getPackage()));
System.out.println("constructors "+JSON.toJSONString(clz.getDeclaredConstructors()[0]));
System.out.println("fields "+JSON.toJSONString(clz.getDeclaredFields()[0]));
System.out.println("method "+JSON.toJSONString(clz.getDeclaredMethods()[0]));
System.out.println("annotation "+JSON.toJSONString(clz.getDeclaredAnnotations()[0]));
}
}
反射--获取指定构造方法创建一个对象
-
Constructor :可以调用任何构造方法,可强行访问
-
Class.newInstance:只能够调用 共有 无参构造方法。当无参方法私有时,报错:java.lang.IllegalAccessException
@Test
public void testConstructors() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException {
//通过反射获取指定的构造方法--主要用来创建对象
Class clz=Student.class;
Constructor con=clz.getDeclaredConstructor(Integer.class);
if(!con.isAccessible()){
con.setAccessible(true);
}
Student student= (Student) con.newInstance(23);
System.out.println("student:"+JSON.toJSONString(student));
Student student1= (Student) clz.newInstance();
System.out.println("student1:"+JSON.toJSONString(student1));
}
反射--获取属性值,为指定属性赋值
@Test
public void testField() throws NoSuchFieldException, IllegalAccessException {
//获取指定属性值
Student student=new Student();
student.setAge(20);
Class clz=Student.class;
Field f=clz.getDeclaredField("age");
if(!f.isAccessible()){
f.setAccessible(true);
}
Object value=f.get(student);
System.out.println(value);
//设置指定属性值
Field field=clz.getDeclaredField("name");
if(!field.isAccessible()){
field.setAccessible(true);
}
field.set(student,"afgahgdahgahdhas");
System.out.println(JSON.toJSONString(student));
}
反射--普通方法的调用
@Test
public void testMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class clz=Student.class;
Student student=new Student();
Method method=clz.getDeclaredMethod("setName",String.class);
if(!method.isAccessible()){
method.setAccessible(true);
}
method.invoke(student,"adghashasd;gasdhgasdfgiophpuioh");
System.out.println(JSON.toJSONString(student, SerializerFeature.WriteMapNullValue));
}
反射--static方法调用
@Test
public void testMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class clz=Student.class;
Student student=new Student();
Method method=clz.getDeclaredMethod("testMain", String.class);
if(!method.isAccessible()){
method.setAccessible(true);
}
method.invoke(null,"adghashasd;gasdhgasdfgiophpuioh");
System.out.println(JSON.toJSONString(student, SerializerFeature.WriteMapNullValue));
}
@Test
public void testMain() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class clz=Student.class;
Method m1=clz.getDeclaredMethod("main",String[].class);
m1.invoke(null,(Object)new String[]{"a","a","a"});
}
反射--破坏泛型检查
@SneakyThrows
@Test
public void testTEF(){
List <String> arrayList=new ArrayList <>();
arrayList.add("adddd");
arrayList.add("bbbbbb");
Class clz=arrayList.getClass();
Method m=clz.getDeclaredMethod("add",Object.class);
m.invoke(arrayList,1000);
System.out.println(JSON.toJSONString(arrayList));
}