目錄
簡介
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));
}