<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] # 類的加載器 當程序要使用某個類時,如果該類還未被加載到內存中,則系統會通過加載,連接,初始化三步來實現對這個類進行初始化。 * 加載 就是指將class文件讀入內存,并為之創建一個Class對象。 任何類被使用時系統都會建立一個Class對象 * 連接 驗證 是否有正確的內部結構,并和其他類協調一致 準備 負責為類的靜態成員分配內存,并設置默認初始化值 解析 將類的二進制數據中的符號引用替換為直接引用 * 初始化 ## 類的初始化時機 1. 創建類的實例 2. 類的靜態變量,或者為靜態變量賦值 3. 類的靜態方法 4. 使用反射方式來強制創建某個類或接口對應的java.lang.Class對象 5. 初始化某個類的子類 6. 直接使用java.exe命令來運行某個主類 ## 類加載器 * 負責將.class文件加載到內在中,并為之生成對應的Class對象。 * 雖然我們不需要關心類加載機制,但是了解這個機制我們就能更好的理解程序的運行 ## 類加載器的組成 * Bootstrap ClassLoader 根類加載器 也被稱為引導類加載器,負責Java核心類的加載 比如System,String等。在JDK中JRE的lib目錄下rt.jar文件中 * Extension ClassLoader 擴展類加載器 負責JRE的擴展目錄中jar包的加載。 在JDK中JRE的lib目錄下ext目錄 * System ClassLoader 系統類加載器 負責在JVM啟動時加載來自java命令的class文件,以及classpath環境變量所指定的jar包和類路徑 ![](https://box.kancloud.cn/436f4a7b093d1fadcb19142cb8521755_1378x1066.jpg) # 反射 ## class類 Class類沒有公共構造方法。Class 對象是在加載類時由 Java 虛擬機以及通過調用類加載器中的 defineClass 方法自動構造的 獲取Class對象的三種方式 **方式一: 通過Object類中的getObject()方法** ~~~ Person p = new Person(); Class c = p.getClass(); ~~~ **方式二: 通過 類名.class 獲取到字節碼文件對象** (任意數據類型都具備一個class靜態屬性,看上去要比第一種方式簡單)。 ~~~ Class c2 = Person.class; ~~~ **方式三: 通過Class類中的方法** (將類名作為字符串傳遞給Class類中的靜態方法forName即可)。 ~~~ Class c3 = Class.forName("com.jdxia.Person"); ~~~ * 注意:第三種和前兩種的區別 前兩種你必須明確Person類型. 后面是指定這種類型的字符串就行.這種擴展更強.我不需要知道你的類.我只提供字符串,按照配置文件加載就可以了 ~~~ Person person = new Person(); Class c1 = person.getClass(); Class c2 = Person.class; Class c3 = Class.forName("study.Person"); ~~~ ## 反射獲取構造方法 在反射機制中,把類中的成員(構造方法、成員方法、成員變量)都封裝成了對應的類進行表示。其中,構造方法使用類Constructor表示。可通過Class類中提供的方法獲取構造方法: * 返回一個構造方法 - public Constructor<T> getConstructor(Class<?>... parameterTypes) 獲取public修飾, 指定參數類型所對應的構造方法 - public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 獲取指定參數類型所對應的構造方法(包含私有的) * 返回多個構造方法 - public Constructor<?>[] getConstructors() 獲取所有的public 修飾的構造方法 - public Constructor<?>[] getDeclaredConstructors() 獲取所有的構造方法(包含私有的) ~~~ //獲取Class對象 Class c = Class.forName("study.Person"); //獲取所有的構造方法 Constructor[] constructors = c.getDeclaredConstructors(); for (Constructor constructor : constructors) { //私有構造也能獲取 System.out.println(constructor); } /** * 獲取一個構造方法 * public Person() */ Constructor constructor = c.getConstructor(null); System.out.println(constructor); //public Person(String name, int a) Constructor constructor1 = c.getDeclaredConstructor(String.class,int.class); System.out.println(constructor1); //private Person(String name) Constructor constructor2 = c.getDeclaredConstructor(String.class); System.out.println(constructor2); ~~~ ## 反射獲取構造方法創建對象 獲取構造方法,步驟如下: 1. 獲取到Class對象 2. 獲取指定的構造方法 3. 通過構造方法類Constructor中的方法,創建對象 public T newInstance(Object... initargs) ~~~ //獲取Class對象 Class c = Class.forName("study.Person"); //獲取構造方法 Constructor constructor = c.getDeclaredConstructor(String.class, int.class); //通過構造方法類中的Constructor的方法創建對象 Object object = constructor.newInstance("jdxia",1); System.out.println(object); ~~~ ## 反射獲取私有構造方法創建對象 AccessibleObject 類是 Field、Method 和 Constructor 對象的父類。它提供了將反射的對象標記為在使用時取消默認 Java 語言訪問控制檢查的能力。 對于公共成員、默認(打包)訪問成員、受保護成員和私有成員,在分別使用 Field、Method 或 Constructor 對象來設置或獲取字段、調用方法,或者創建和初始化類的新實例的時候,會執行訪問檢查。常用方法如下: * public void setAccessible(boolean flag) throws SecurityException 參數值為 true 則指示反射的對象在使用時應該取消 Java 語言訪問檢查。參數值為 false 則指示反射的對象應該實施 Java 語言訪問檢查。 獲取私有構造方法,步驟如下: 1. 獲取到Class對象 2. 獲取指定的構造方法 3. 暴力訪問, 通過setAccessible(boolean flag)方法 4. 通過構造方法類Constructor中的方法,創建對象 public T newInstance(Object... initargs) ~~~ //獲取Class對象 Class c = Class.forName("study.Person"); //獲取構造方法 Constructor constructor = c.getDeclaredConstructor(String.class); //暴力反射,取消java語言訪問檢查 constructor.setAccessible(true); Object object = constructor.newInstance("jdxia"); System.out.println(object); ~~~ ## 反射獲取成員變量 在反射機制中,把類中的成員變量使用類Field表示。可通過Class類中提供的方法獲取成員變量: * 返回一個成員變量 - public Field getField(String name) 獲取指定的 public修飾的變量 - public Field getDeclaredField(String name) 獲取指定的任意變量 * 返回多個成員變量 - public Field[] getFields() 獲取所有public 修飾的變量 - public Field[] getDeclaredFields() 獲取所有的 變量 (包含私有) ~~~ //獲取Class對象 Class c = Class.forName("study.Person"); //獲取成員變量 //多個變量 Field[] fields = c.getDeclaredFields(); for (Field field : fields) { System.out.println(field); } //一個變量 Field name = c.getField("name"); System.out.println(name); //私有的 Field a = c.getDeclaredField("a"); System.out.println(a); ~~~ ## 反射獲取指定的成員變量,進行賦值與取值 獲取成員變量,步驟如下: 1. 獲取Class對象 2. 獲取構造方法 3. 通過構造方法,創建對象 4. 獲取指定的成員變量(私有成員變量,通過setAccessible(boolean flag)方法暴力訪問) 5. 通過方法,給指定對象的指定成員變量賦值或者獲取值 * public void set(Object obj, Object value) 在指定對象obj中,將此 Field 對象表示的成員變量設置為指定的新值 * public Object get(Object obj) 返回指定對象obj中,此 Field 對象表示的成員變量的值 ~~~ //獲取Class對象 Class c = Class.forName("study.Person"); //獲取構造方法 Constructor constructor = c.getDeclaredConstructor(String.class, int.class); //通過構造方法創建對象 Object object = constructor.newInstance("jdxia", 1); //獲取指定的成員變量 Field name = c.getDeclaredField("name"); Field a = c.getDeclaredField("a"); //取消語言訪問檢查 a.setAccessible(true); //通過方法,給指定對象的指定成員變量賦值或者取值 System.out.println("name = "+name.get(object)); System.out.println("a = "+a.get(object)); //賦值 name.set(object, "x"); a.set(object, 2); System.out.println("name = "+name.get(object)); System.out.println("a = "+a.get(object)); ~~~ ## 反射獲取成員方法 在反射機制中,把類中的成員方法使用類Method表示。可通過Class類中提供的方法獲取成員方法: * 返回獲取一個方法: - public Method getMethod(String name, Class<?>... parameterTypes) 獲取public 修飾的方法 - public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 獲取任意的方法,包含私有的 參數1: name 要查找的方法名稱; 參數2: parameterTypes 該方法的參數類型 * 返回獲取多個方法: - public Method[] getMethods() 獲取本類與父類中所有public 修飾的方法 - public Method[] getDeclaredMethods() 獲取本類中所有的方法(包含私有的) ~~~ //獲取Class對象 Class c = Class.forName("study.Person"); //獲取多個方法 Method[] methods = c.getDeclaredMethods(); for (Method method : methods) { System.out.println(method); } //獲取一個方法 //private void param(String param) Method method = c.getDeclaredMethod("param",String.class); System.out.println(method); ~~~ ## 反射調用指定的方法 獲取成員方法,步驟如下: 1. 獲取Class對象 2. 獲取構造方法 3. 通過構造方法,創建對象 4. 獲取指定的方法 5. 執行找到的方法 * public Object invoke(Object obj, Object... args) 執行指定對象obj中,當前Method對象所代表的方法,方法要傳入的參數通過args指定。 ~~~ //獲取Class對象 Class c = Class.forName("study.Person"); //獲取構造方法 Constructor constructor = c.getDeclaredConstructor(String.class, int.class); //通過構造方法創建對象 Object obj = constructor.newInstance("jdxia",1); //獲取一個方法 //private void param(String param) Method method = c.getDeclaredMethod("param",String.class); //取消語法檢查 method.setAccessible(true); Object result = method.invoke(obj,"傳遞的參數"); //獲取函數返回值 System.out.println(result); ~~~ ## 泛型擦除 思考,將已存在的ArrayList<Integer>集合中添加一個字符串數據,如何實現呢? 我來告訴大家,其實程序編譯后產生的.class文件中是沒有泛型約束的,這種現象我們稱為泛型的擦除。那么,我們可以通過反射技術,來完成向有泛型約束的集合中,添加任意類型的元素 ~~~ ArrayList<Integer> list = new ArrayList<Integer>(); //添加元素到集合 list.add(new Integer(30)); list.add(new Integer("12345")); list.add(123); //list.add("哈哈");//因為有泛型類型的約束 System.out.println(list); //通過反射技術,實現添加任意類型的元素 //1, 獲取字節碼文件對象 //Class c = list.getClass(); //Class c = ArrayList.class; Class c = Class.forName("java.util.ArrayList"); //2, 找到add()方法 // public boolean add(E e) Method addMethod = c.getMethod("add", Object.class); //3, 執行add()方法 addMethod.invoke(list, "哈哈");// list.add("哈哈"); System.out.println(list); ~~~ ## 反射配置文件 * 通過反射配置文件,運行配置文件中指定類的對應方法 讀取Peoperties.txt文件中的數據,通過反射技術,來完成Person對象的創建 Peoperties.txt文件內容如下: ~~~ className=study.Person methodName=method5 ~~~ 讀取配置文件,調用指定類中的對應方法 ~~~ // 通過Properties集合從文件中讀取數據 Properties prop = new Properties(); // 讀取文件中的數據到集合中 prop.load(new FileInputStream("properties.txt")); // 獲取鍵所對應的值 String className = prop.getProperty("className"); System.out.println(className); // 1,獲取Person.class 字節碼文件對象 Class c = Class.forName(className); // 2,獲取構造方法 // public Person(String name, int age, String address) Constructor con = c.getConstructor(String.class, int.class, String.class); // 3,創建對象 Object obj = con.newInstance("小明", 20, "中國"); System.out.println(obj); // 4,獲取指定的方法 // private void method5(){} String methodName = prop.getProperty("methodName"); Method m5 = c.getDeclaredMethod(methodName, null); // 5,開啟暴力訪問 m5.setAccessible(true); // 6,執行找到的方法 m5.invoke(obj, null); ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看