標籤:get simple hand 參數 lang illegal loader anti 添加
【1】反射機制是在運行狀態中,對於任何一個類,都能夠知道這個類的所有屬性和方法;
【2】對於任意一個對象,都能夠調用它的任意一個屬性和方法;
像這種動態擷取類的資訊以及動態調用對象的方法的騷操作稱為java語言的反射機制。
二、Java反射機制能夠擷取及操作哪些資訊?
【1】擷取類的包名 + 類名
1 package com.zyy.test.reflect; 2 3 public class TestReflect { 4 5 public static void main(String[] args) throws ClassNotFoundException { 6 Class<?> class1 = TestReflect.class; 7 Class<?> class2 = new TestReflect().getClass(); 8 Class<?> class3 = Class.forName("com.zyy.test.reflect.TestReflect"); 9 10 System.out.println("包名+類名:" + class1.getName());11 System.out.println("類名" + class1.getSimpleName());12 System.out.println("包名+類名:" + class2.getName());13 System.out.println("類名" + class2.getSimpleName());14 System.out.println("包名+類名:" + class3.getName());15 System.out.println("類名" + class3.getSimpleName());16 17 /*18 列印結果如下:19 包名+類名:com.zyy.test.reflect.TestReflect20 類名TestReflect21 包名+類名:com.zyy.test.reflect.TestReflect22 類名TestReflect23 包名+類名:com.zyy.test.reflect.TestReflect24 類名TestReflect25 */26 }27 28 }
【2】擷取某個類的父類與實現的介面資訊
1 package com.zyy.test.reflect; 2 3 import java.io.Serializable; 4 5 public class TestReflect implements Serializable{ 6 7 private static final long serialVersionUID = -8047590384784013451L; 8 9 public static void main(String[] args) throws ClassNotFoundException {10 Class<?> clazz = Class.forName("com.zyy.test.reflect.TestReflect");11 //擷取父類資訊12 System.out.println("父類:" + clazz.getSuperclass().getName());13 //擷取實現的所有介面資訊14 Class<?>[] interfaces = clazz.getInterfaces();15 for (int i = 0; i < interfaces.length; i++) {16 System.out.println("介面:" + interfaces[i].getName());17 }18 19 /*列印結果如下:20 父類:java.lang.Object21 介面:java.io.Serializable22 */23 }24 25 }
【3】擷取某個類的構造資訊以及使用構造進行賦值
1 package com.zyy.test.reflect; 2 3 import java.lang.reflect.Constructor; 4 import java.lang.reflect.InvocationTargetException; 5 import java.math.BigDecimal; 7 8 public class TestReflect { 9 10 public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, 11 IllegalArgumentException, InvocationTargetException {12 13 Class<?> clazz = Class.forName("com.zyy.test.reflect.BookFacaed");14 Constructor<?>[] constructors = clazz.getConstructors();15 16 for (int i = 0; i < constructors.length; i++) {17 System.out.println("構造" + i + constructors[i].getName() + "的參數為:");18 //擷取構造的參數資訊19 Class<?>[] types = constructors[i].getParameterTypes();20 for (int j = 0; j < types.length; j++) {21 System.out.println(types[j].getName() + " ");22 }23 }24 25 /*列印結果:26 構造0com.zyy.test.reflect.BookFacaed的參數為:27 java.lang.String 28 java.math.BigDecimal 29 構造1com.zyy.test.reflect.BookFacaed的參數為:30 java.lang.String 31 構造2com.zyy.test.reflect.BookFacaed的參數為:32 */33 34 //執行個體化擁有2個參數的構造方法35 BookFacaed bookFacaed = (BookFacaed)constructors[0].newInstance("《資料結構》", new BigDecimal(100));36 System.out.println(bookFacaed); //調用實體的toString方法列印37 38 //通過反射機制直接執行個體化對象39 BookFacaed bookFacaed2 = (BookFacaed)clazz.newInstance();40 bookFacaed2.setName("《資料結構》");41 bookFacaed2.setPrice(new BigDecimal(100));42 System.out.println(bookFacaed2);43 }44 45 }46 47 class BookFacaed {48 private String name;49 50 private BigDecimal price;51 52 public BookFacaed () {}53 54 public BookFacaed (String name) {55 this.name = name;56 }57 58 public BookFacaed (String name, BigDecimal price) {59 this.name = name;60 this.price = price;61 }62 63 public String getName() {64 return name;65 }66 67 public void setName(String name) {68 this.name = name;69 }70 71 public BigDecimal getPrice() {72 return price;73 }74 75 public void setPrice(BigDecimal price) {76 this.price = price;77 }78 79 @Override80 public String toString() {81 return name + "的價格為:" + price;82 }83 }
【4】擷取某個類的所有屬性資訊
1 package com.zyy.test.reflect; 2 3 import java.lang.reflect.Field; 4 import java.lang.reflect.Modifier;public class TestReflect { 5 6 public static void main(String[] args) throws ClassNotFoundException { 7 Class<?> clazz = Class.forName("com.zyy.test.reflect.BookFacaed"); 8 Field[] fields = clazz.getDeclaredFields(); 9 for (int i = 0; i < fields.length; i++) {10 //獲得類屬性的修飾符11 String pri = Modifier.toString(fields[i].getModifiers());12 //獲得類屬性的類型13 Class<?> type = fields[i].getType();14 15 System.out.println(pri + " " + type.getSimpleName() + " " + fields[i].getName());16 /*列印結果:17 private String name18 private BigDecimal price19 */20 }21 22 /*如果要擷取類的介面或者父類的屬性使用下面的方法擷取*/23 Field[] fields2 = clazz.getFields();24 }25 26 }
【5】擷取某個類的所有方法及其屬性資訊
1 package com.zyy.test.reflect; 2 3 import java.lang.reflect.Method; 4 import java.lang.reflect.Modifier; 5 import java.math.BigDecimal; 6 7 8 public class TestReflect { 9 10 public static void main(String[] args) throws ClassNotFoundException {11 Class<?> clazz = Class.forName("com.zyy.test.reflect.BookFacaed");12 13 Method[] methods = clazz.getMethods();14 for (int i = 0; i < methods.length; i++) {15 System.out.println("方法" + (i + 1));16 //擷取方法的修飾符17 String pri = Modifier.toString(methods[i].getModifiers());18 //擷取方法的傳回型別19 Class<?> type = methods[i].getReturnType();20 //擷取方法的持有參數21 Class<?>[] params = methods[i].getParameterTypes();22 for (int j = 0; j < params.length; j++) {23 System.out.println(params[j].getName());24 }25 //擷取方法的拋出異常26 Class<?>[] excTypes = methods[i].getExceptionTypes();27 for (int j = 0; j < excTypes.length; j++) {28 System.out.println(excTypes[j].getName());29 }30 }31 }32 33 }
【6】反射機制調用某個類的某個方法
1 package com.zyy.test.reflect; 2 3 import java.lang.reflect.InvocationTargetException; 4 import java.lang.reflect.Method; 5 import java.math.BigDecimal; 6 7 public class TestReflect { 8 9 public static void main(String[] args) throws NoSuchMethodException, SecurityException, ClassNotFoundException, 10 IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {11 12 Class<?> clazz = Class.forName("com.zyy.test.reflect.BookFacaed");13 //調用BookFacaed的addBook()方法14 Method method = clazz.getMethod("addBook", String.class);15 method.invoke(clazz.newInstance(), "《資料結構》");16 }17 18 }19 20 class BookFacaed {21 private String name;22 23 private BigDecimal price;24 25 public BookFacaed () {}26 27 public BookFacaed (String name) {28 this.name = name;29 }30 31 public BookFacaed (String name, BigDecimal price) {32 this.name = name;33 this.price = price;34 }35 36 public void addBook(String name) {37 System.out.println("添加書:" + name);38 }39 40 public String getName() {41 return name;42 }43 44 public void setName(String name) {45 this.name = name;46 }47 48 public BigDecimal getPrice() {49 return price;50 }51 52 public void setPrice(BigDecimal price) {53 this.price = price;54 }55 56 @Override57 public String toString() {58 return name + "的價格為:" + price;59 }60 }
【7】通過反射機制操作某個類的屬性
1 package com.zyy.test.reflect; 2 3 import java.lang.reflect.Field; 4 import java.math.BigDecimal; 5 6 public class TestReflect { 7 8 public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, 9 SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException {10 11 Class<?> clazz = Class.forName("com.zyy.test.reflect.BookFacaed");12 Object obj = clazz.newInstance();13 //調用BookFacaed的name屬性,並賦值14 Field field = clazz.getDeclaredField("name");15 field.setAccessible(true); //操作屬性修飾符為private則必須用此申明16 field.set(obj, "《資料結構》");17 18 System.out.println(field.get(obj));19 }20 21 }
三、Java反射機制能夠協助我們做什嗎?
【1】打破泛型的約束
1 package com.zyy.test.reflect; 2 3 import java.lang.reflect.InvocationTargetException; 4 import java.lang.reflect.Method; 5 import java.math.BigDecimal; 6 import java.util.ArrayList; 7 import java.util.List; 8 9 public class TestReflect {10 11 public static void main(String[] args) throws NoSuchMethodException, SecurityException, 12 IllegalAccessException, IllegalArgumentException, InvocationTargetException {13 14 List<Integer> list = new ArrayList<Integer>();15 //設定了以上泛型之後,list集合中是無法插入String或者其他類型的資料的16 //通過泛型我們便可打破這個約束,代碼如下17 Method method = list.getClass().getMethod("add", Object.class);18 method.invoke(list, "看插入了一個String資料");19 20 System.out.println(list.get(0));21 }22 23 }
【2】反射機制實現動態代理
Spring的一個核心設計思想便是AOP(面向切面編程),那麼AOP是通過動態代理實現的,而動態代理則用到了反射機制;
用了反射機制的好處在於,一個代理就能處理所有的委託,而不用一個委託類就建立一個代理;
1 package com.zyy.test.reflect; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 7 8 public class TestReflect { 9 10 public static void main(String[] args) {11 //建立代理類並綁定委託類12 FruitProxy proxy = new FruitProxy();13 Fruit fruit = (Fruit) proxy.bind(new Apple());14 fruit.eatFruit();15 }16 17 }18 19 interface Fruit {20 public void eatFruit();21 }22 23 //委託類24 class Apple implements Fruit {25 public void eatFruit() {26 System.out.println("eat Apple");27 }28 }29 30 //代理類31 class FruitProxy implements InvocationHandler{32 private Object obj;33 34 //綁定對象35 public Object bind(Object obj) {36 this.obj = obj;37 return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);38 }39 40 @Override41 public Object invoke(Object proxy, Method method, Object[] args)42 throws Throwable {43 System.out.println("這裡添加執行內容,<aop:before/>標籤熟悉吧,作用一樣");44 Method result = (Method) method.invoke(obj, args);45 System.out.println("這裡添加執行內容,<aop:after/>標籤熟悉吧,作用一樣");46 47 return result;48 }49 50 }
【3】反射機制應用於原廠模式
對於普通的工廠,新增一個子類的時候,工廠就需要進行調整,而加入反射機制後,工廠則不需要關心你有多少個子類;
1 package com.zyy.test.reflect; 2 3 public class TestReflect { 4 5 public static void main(String[] args) throws InstantiationException, 6 IllegalAccessException, ClassNotFoundException { 7 8 Fruit fruit = (Fruit) Factory.getInstance("com.zyy.test.reflect.Orange"); 9 fruit.eatFruit();10 }11 12 }13 14 interface Fruit {15 public void eatFruit();16 }17 18 class Apple implements Fruit {19 public void eatFruit() {20 System.out.println("eat Apple");21 }22 }23 24 class Orange implements Fruit {25 public void eatFruit() {26 System.out.println("eat Orange");27 }28 }29 30 class Factory {31 public static Object getInstance (String className) throws InstantiationException, 32 IllegalAccessException, ClassNotFoundException {33 34 Object obj = Class.forName(className).newInstance();35 return obj;36 }37 38 }
Java反射機制能夠擷取的資訊,與應用