網站規(guī)劃怎么寫英文seo兼職
目錄
基本概念
定義
用途
反射相關的類
反射基本原理
Class 類中的相關方法
常用獲得類相關的方法
常用獲得類中屬性相關的方法
常用獲得類中構造器相關的方法
常用獲得類中方法相關的方法
實例理解
反射優(yōu)缺點
基本概念
定義
- Java 的反射(reflection)機制是一種強大功能,它可以讓我們在運行時動態(tài)地獲取和操作 類 或 對象 的信息
實例理解
- 我們可以通過反射機制來創(chuàng)建一個類的對象,而不需要使用 new 關鍵字
- 我們也可以通過反射機制來訪問或修改一個對象的私有屬性或方法,而不需要遵循封裝原則
- 我們還可以通過反射機制來調用一個對象的任意方法,而不需要知道它的參數(shù)類型或返回值類型
用途
典型用途一:
- 在開發(fā)第三方應用時,我們可能會遇到一些類的成員變量、方法或屬性是私有的,或者只對系統(tǒng)應用開放,這就意味著我們不能直接訪問這些成員或方法
- 這時我們便可以在運行時 通過 Java 的反射機制 來動態(tài)地訪問和操作類的內部成員,包括私有成員和方法
典型用途二:
- 反射在開發(fā)通用框架 Spring 中起著重要的作用
- 在Spring 框架中,所有類(Bean)都由 Spring 容器進行管理,這些 Bean 可以通過 XML 配置或注解來配置
- 當我們從容器中獲取Bean 以進行依賴注入時,容器會讀取配置信息,這些配置信息包含了類的信息,比如類的名稱、屬性、方法等
- Spring根據(jù)這些信息 動態(tài)地創(chuàng)建這些類的實例,這個過程就是所謂的 依賴注入,該過程中,反射起到了關鍵作用
- Spring 使用反射來動態(tài)地創(chuàng)建類的實例,調用方法,以及設置屬性值
反射相關的類
反射基本原理
- Java 的反射機制是基于 java.lang.Class 類實現(xiàn)的
- 當我們編譯一個 Java 文件時,會生成一個 .class 文件
- 當 JVM 加載這個 .class 文件時,會將其解析為一個 java.lang.Class 類的對象
- 在程序運行時,每個 Java 文件都會被 JVM 解析為一個 Class 類的實例
- 這個 Class 類的實例包含了該 Java 文件中所定義類的所有信息,包括類的名稱、屬性、方法等
- 我們可以通過 Java 的反射機制來操作這個 Class 類的實例
- 具體來說,我們可以使用反射來獲取類的屬性和方法,甚至可以添加或修改類的屬性和方法
- 這使得我們可以在運行時動態(tài)地操作類,使其成為一個 動態(tài)的類
類名 用途 Class 類 代表類的實體,在運行的 Java 應用程序中表示類和接口 Field 類 代表類的成員變量、類的屬性 Method 類 代表類的方法 Constructor 類 代表類的構造方法
Class 類中的相關方法
常用獲得類相關的方法
方法 用途 getClassLoader() 獲得類的加載器 getDeclaredClasses() 返回一個數(shù)組,數(shù)組中包含該類中所有類和接口類的對象(包括私有的) forName(String className) 根據(jù)類名返回類的對象 newInstance() 創(chuàng)建類的實例 getName() 獲得類的完整路徑名字 常用獲得類中屬性相關的方法
方法 用途 getField(String name) 獲得某個公有的屬性對象 getFields() 獲得所有公有的屬性對象 getDeclaredField(String name) 獲得某個屬性對象 getDeclaredFields() 獲得所有屬性對象 常用獲得類中構造器相關的方法
方法 用途 getConstructor(Class <?> parameterTypes) 獲得該類中與參數(shù)類型匹配的公有構造方法 getConstructors() 獲得該類的所有公有構造方法 getDeclaredConstructor(Class <?> parameterTypes) 獲得該類中與參數(shù)類型匹配的構造方法 getDeclaredConstructors() 獲得該類所有構造方法 常用獲得類中方法相關的方法
方法 用途 getMethod(String name, Class <?> parameterTypes) 獲得該類某個公有的方法 getMethods() 獲得該類所有公有的方法 getDeclaredMethod(String name, Class <?> parameterTypes) 獲得該類某個方法 getDeclaredMethods() 獲得該類所有方法
實例理解
- 此處我們先創(chuàng)建一個 Student 類
class Student{//私有屬性nameprivate String name = "master";//公有屬性agepublic int age = 18;//不帶參數(shù)的構造方法public Student(){System.out.println("Student()");}private Student(String name,int age) {this.name = name;this.age = age;System.out.println("Student(String,name)");}private void eat(){System.out.println("make hamburger!");}public void sleep(){System.out.println("go to bed!");}private void function(String str) {System.out.println(str);}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';} }
- 此處介紹三種方式來獲取 Student 的 Class 對象
public class Demo1 {public static void main(String[] args) { // 有三種方式可以獲取 Class 對象Student student1 = new Student(); // 1、通過對象的 getClass() 方法Class<?> c1 = student1.getClass(); // 2、通過類名 .class 獲取Class<?> c2 = Student.class; // 3、通過調用 Class.forName() 方法獲取了 Student 類的 Class 對象 // Class.forName() 方法需要一個類的全限定名(包括 包名和類名) 作為參數(shù) // 此處的 ? 是一個通配符,用于表示未知類型 // 當我們聲明一個泛型變量時,如果我們不確定或不關心實際的類型參數(shù),我們可以使用 ? 來表示Class<?> c3 = null;try {c3 = Class.forName("Student");} catch (ClassNotFoundException e) {throw new RuntimeException(e);} // 此處證明通過上述三種方式所獲取的 Class 對象 都是同一個System.out.println((c1.equals(c2) && c1.equals(c3) && c2.equals(c3)) ? "true" : "false");} }
- 此處我們通過反射機制創(chuàng)建一個對象
import java.lang.reflect.InvocationTargetException;public class ReflectClassDemo {// 通過反射創(chuàng)建一個對象public static void reflectNewInstance() throws InstantiationException, IllegalAccessException, ClassNotFoundException {Class<?> c3 = Class.forName("Student"); // 通過調用 Class 類的 newInstance() 方法來創(chuàng)建一個 c3 對應類的新實例 // newInstance() 方法調用的是這個類的無參構造函數(shù) // 如果這個類沒有無參構造函數(shù),或者無參構造函數(shù)是私有的,那么 newInstance 會拋出一個異常 // 因為 newInstance() 方法返回的類型為 Object 類 所以需要類型轉換,此處轉換為 Student 類Student student = (Student) c3.newInstance();System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectNewInstance();} }
運行結果:
- 此處我們通過反射機制獲取私有的構造方法
import java.lang.reflect.Constructor;public class ReflectClassDemo {// 通過反射獲取私有的構造方法public static void reflectPrivateConstructor() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class<?> c3 = Class.forName("Student");Constructor<?> constructor = c3.getDeclaredConstructor(String.class,int.class); // 注意只要是涉及到 private 都要使用 setAccessible(true) 來打開權限,此處的構造方法為私有的constructor.setAccessible(true); // 此處利用構造方法 修改年齡和性別Student student = (Student)constructor.newInstance("xiaolin",20);System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectPrivateConstructor();} }
運行結果:
- 此處我們通過反射機制獲取私有屬性
import java.lang.reflect.Field;public class ReflectClassDemo {// 通過反射獲取私有屬性public static void reflectPrivateField() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {Class<?> c3 = Class.forName("Student");Field field = c3.getDeclaredField("name"); // 注意只要是涉及到 private 都要使用 setAccessible(true) 來打開權限,此處的 name 屬性是私有的field.setAccessible(true);Student student = (Student) c3.newInstance(); // 此處修改私有屬性field.set(student,"haoran");System.out.println(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectPrivateField();} }
運行結果:
- 此處我們通過反射機制獲取私有方法
import java.lang.reflect.Method;public class ReflectClassDemo {// 通過反射獲取私有方法public static void reflectPrivateMethod() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {Class<?> c3 = Class.forName("Student");Method method1 = c3.getDeclaredMethod("function", String.class);Method method2 = c3.getDeclaredMethod("sleep"); // 注意只要是涉及到 private 都要使用 setAccessible(true) 來打開權限,此處的 function 方法是私有的method1.setAccessible(true);Student student = (Student) c3.newInstance(); // 此處給 function 方法傳參method1.invoke(student,"此處利用反射機制給 function 方法傳個字符串參數(shù)"); // 此處調用 sleep 方法,該方法為 public 無需額外打開權限,直接調用即可method2.invoke(student);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {reflectPrivateMethod();} }
運行結果:
反射優(yōu)缺點
優(yōu)點
- 對于任意一個類,都能夠知道這個類的所有屬性和方法,對于任意一個類都能調用它的任意一個方法
- 增加程序的靈活性和擴展性,降低耦合性,提高自適應性
- 反射已經運用在很多流行框架,典型代表為 Spring
缺點
- 使用反射會有效率問題,會導致程序效率降低
- 反射技術繞過了源代碼的技術,因而會帶來維護問題
- 反射代碼比相應的直接代碼更復雜
總結:
- 雖然反射非常強大,但也需要謹慎使用
- 我們需要在反射帶來的靈活性和可擴展性與其帶來的性能開銷、維護問題和代碼復雜性之間找到一個平衡
- 某些情況下,比如開發(fā)通用的框架,使用反射式非常有價值的
- 但在其他情況下,我們可能更傾向于使用更簡單、更直接的代碼