java學習之反射機制學習總結,java反射機制的優點

本文目錄一覽:

java中的反射機制是什麼?有什麼作用呢?求解,謝謝。

Java反射機制詳解

1. 反射機制是什麼

反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。

2. 反射機制能做什麼

反射機制主要提供了以下功能:

在運行時判斷任意一個對象所屬的類;

在運行時構造任意一個類的對象;

在運行時判斷任意一個類所具有的成員變量和方法;

在運行時調用任意一個對象的方法;

生成動態代理。

3. 反射機制的相關API

通過一個對象獲得完整的包名和類名

package net.xsoftlab.baike;

public class TestReflect {

    public static void main(String[] args) throws Exception {

        TestReflect testReflect = new TestReflect();

        System.out.println(testReflect.getClass().getName());

        // 結果 net.xsoftlab.baike.TestReflect

    }

}

實例化Class類對象

package net.xsoftlab.baike;

public class TestReflect {

    public static void main(String[] args) throws Exception {

        Class? class1 = null;

        Class? class2 = null;

        Class? class3 = null;

        // 一般採用這種形式

        class1 = Class.forName(“net.xsoftlab.baike.TestReflect”);

        class2 = new TestReflect().getClass();

        class3 = TestReflect.class;

        System.out.println(“類名稱   ” + class1.getName());

        System.out.println(“類名稱   ” + class2.getName());

        System.out.println(“類名稱   ” + class3.getName());

    }

}

獲取一個對象的父類與實現的接口

package net.xsoftlab.baike;

import java.io.Serializable;

public class TestReflect implements Serializable {

    private static final long serialVersionUID = -2862585049955236662L;

    public static void main(String[] args) throws Exception {

        Class? clazz = Class.forName(“net.xsoftlab.baike.TestReflect”);

        // 取得父類

        Class? parentClass = clazz.getSuperclass();

        System.out.println(“clazz的父類為:” + parentClass.getName());

        // clazz的父類為: java.lang.Object

        // 獲取所有的接口

        Class? intes[] = clazz.getInterfaces();

        System.out.println(“clazz實現的接口有:”);

        for (int i = 0; i  intes.length; i++) {

            System.out.println((i + 1) + “:” + intes[i].getName());

        }

        // clazz實現的接口有:

        // 1:java.io.Serializable

    }

}

獲取某個類中的全部構造函數 – 詳見下例

通過反射機制實例化一個類的對象

package net.xsoftlab.baike;

import java.lang.reflect.Constructor;

public class TestReflect {

    public static void main(String[] args) throws Exception {

        Class? class1 = null;

        class1 = Class.forName(“net.xsoftlab.baike.User”);

        // 第一種方法,實例化默認構造方法,調用set賦值

        User user = (User) class1.newInstance();

        user.setAge(20);

        user.setName(“Rollen”);

        System.out.println(user);

        // 結果 User [age=20, name=Rollen]

        // 第二種方法 取得全部的構造函數 使用構造函數賦值

        Constructor? cons[] = class1.getConstructors();

        // 查看每個構造方法需要的參數

        for (int i = 0; i  cons.length; i++) {

            Class? clazzs[] = cons[i].getParameterTypes();

            System.out.print(“cons[” + i + “] (“);

            for (int j = 0; j  clazzs.length; j++) {

                if (j == clazzs.length – 1)

                    System.out.print(clazzs[j].getName());

                else

                    System.out.print(clazzs[j].getName() + “,”);

            }

            System.out.println(“)”);

        }

        // 結果

        // cons[0] (java.lang.String)

        // cons[1] (int,java.lang.String)

        // cons[2] ()

        user = (User) cons[0].newInstance(“Rollen”);

        System.out.println(user);

        // 結果 User [age=0, name=Rollen]

        user = (User) cons[1].newInstance(20, “Rollen”);

        System.out.println(user);

        // 結果 User [age=20, name=Rollen]

    }

}

class User {

    private int age;

    private String name;

    public User() {

        super();

    }

    public User(String name) {

        super();

        this.name = name;

    }

    public User(int age, String name) {

        super();

        this.age = age;

        this.name = name;

    }

    public int getAge() {

        return age;

    }

    public void setAge(int age) {

        this.age = age;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    @Override

    public String toString() {

        return “User [age=” + age + “, name=” + name + “]”;

    }

}

獲取某個類的全部屬性

package net.xsoftlab.baike;

import java.io.Serializable;

import java.lang.reflect.Field;

import java.lang.reflect.Modifier;

public class TestReflect implements Serializable {

    private static final long serialVersionUID = -2862585049955236662L;

    public static void main(String[] args) throws Exception {

        Class? clazz = Class.forName(“net.xsoftlab.baike.TestReflect”);

        System.out.println(“===============本類屬性===============”);

        // 取得本類的全部屬性

        Field[] field = clazz.getDeclaredFields();

        for (int i = 0; i  field.length; i++) {

            // 權限修飾符

            int mo = field[i].getModifiers();

            String priv = Modifier.toString(mo);

            // 屬性類型

            Class? type = field[i].getType();

            System.out.println(priv + ” ” + type.getName() + ” ” + field[i].getName() + “;”);

        }

         

        System.out.println(“==========實現的接口或者父類的屬性==========”);

        // 取得實現的接口或者父類的屬性

        Field[] filed1 = clazz.getFields();

        for (int j = 0; j  filed1.length; j++) {

            // 權限修飾符

            int mo = filed1[j].getModifiers();

            String priv = Modifier.toString(mo);

            // 屬性類型

            Class? type = filed1[j].getType();

            System.out.println(priv + ” ” + type.getName() + ” ” + filed1[j].getName() + “;”);

        }

    }

}

通過反射機制調用某個類的方法

package net.xsoftlab.baike;

import java.lang.reflect.Method;

public class TestReflect {

    public static void main(String[] args) throws Exception {

        Class? clazz = Class.forName(“net.xsoftlab.baike.TestReflect”);

        // 調用TestReflect類中的reflect1方法

        Method method = clazz.getMethod(“reflect1”);

        method.invoke(clazz.newInstance());

        // Java 反射機制 – 調用某個類的方法1.

        // 調用TestReflect的reflect2方法

        method = clazz.getMethod(“reflect2”, int.class, String.class);

        method.invoke(clazz.newInstance(), 20, “張三”);

        // Java 反射機制 – 調用某個類的方法2.

        // age – 20. name – 張三

    }

    public void reflect1() {

        System.out.println(“Java 反射機制 – 調用某個類的方法1.”);

    }

    public void reflect2(int age, String name) {

        System.out.println(“Java 反射機制 – 調用某個類的方法2.”);

        System.out.println(“age – ” + age + “. name – ” + name);

    }

}

通過反射機制操作某個類的屬性

package net.xsoftlab.baike;

import java.lang.reflect.Field;

public class TestReflect {

    private String proprety = null;

    public static void main(String[] args) throws Exception {

        Class? clazz = Class.forName(“net.xsoftlab.baike.TestReflect”);

        Object obj = clazz.newInstance();

        // 可以直接對 private 的屬性賦值

        Field field = clazz.getDeclaredField(“proprety”);

        field.setAccessible(true);

        field.set(obj, “Java反射機制”);

        System.out.println(field.get(obj));

    }

}

4. 反射機制的應用實例

在泛型為Integer的ArrayList中存放一個String類型的對象。

package net.xsoftlab.baike;

import java.lang.reflect.Method;

import java.util.ArrayList;

public class TestReflect {

    public static void main(String[] args) throws Exception {

        ArrayListInteger list = new ArrayListInteger();

        Method method = list.getClass().getMethod(“add”, Object.class);

        method.invoke(list, “Java反射機制實例。”);

        System.out.println(list.get(0));

    }

}

通過反射取得並修改數組的信息

package net.xsoftlab.baike;

import java.lang.reflect.Array;

public class TestReflect {

    public static void main(String[] args) throws Exception {

        int[] temp = { 1, 2, 3, 4, 5 };

        Class? demo = temp.getClass().getComponentType();

        System.out.println(“數組類型: ” + demo.getName());

        System.out.println(“數組長度  ” + Array.getLength(temp));

        System.out.println(“數組的第一個元素: ” + Array.get(temp, 0));

        Array.set(temp, 0, 100);

        System.out.println(“修改之後數組第一個元素為: ” + Array.get(temp, 0));

    }

}

將反射機制應用於工廠模式

package net.xsoftlab.baike;

interface fruit {

    public abstract void eat();

}

class Apple implements fruit {

    public void eat() {

        System.out.println(“Apple”);

    }

}

class Orange implements fruit {

    public void eat() {

        System.out.println(“Orange”);

    }

}

class Factory {

    public static fruit getInstance(String ClassName) {

        fruit f = null;

        try {

            f = (fruit) Class.forName(ClassName).newInstance();

        } catch (Exception e) {

            e.printStackTrace();

        }

        return f;

    }

}

/**

 * 對於普通的工廠模式當我們在添加一個子類的時候,就需要對應的修改工廠類。 當我們添加很多的子類的時候,會很麻煩。

 * Java 工廠模式可以參考

 * 

 * 

 * 現在我們利用反射機制實現工廠模式,可以在不修改工廠類的情況下添加任意多個子類。

 * 

 * 但是有一點仍然很麻煩,就是需要知道完整的包名和類名,這裡可以使用properties配置文件來完成。

 * 

 * java 讀取 properties 配置文件 的方法可以參考

 * 

 * 

 * @author xsoftlab.net

 */

public class TestReflect {

    public static void main(String[] args) throws Exception {

        fruit f = Factory.getInstance(“net.xsoftlab.baike.Apple”);

        if (f != null) {

            f.eat();

        }

    }

}

我有一個微信公眾號,經常會分享一些Java技術相關的乾貨,還有一些學習資源。

如果你喜歡我的分享,可以用微信搜索“Java團長”或者“javatuanzhang”關注。

學習java應該如何理解反射?

反射機制:所謂的反射機制就是java語言在運行時擁有一項自觀的能力。通過這種能力可以徹底的了解自身的情況為下一步的動作做準備。

下面具體介紹一下java的反射機制。

Java的反射機制的實現要藉助於4個類:class,Constructor,Field,Method;

其中class代表的時類對 象,Constructor-類的構造器對象,Field-類的屬性對象,Method-類的方法對象。通過這四個對象我們可以粗略的看到一個類的各個組 成部分。

Java反射的作用:

在Java運行時環境中,對於任意一個類,可以知道這個類有哪些屬性和方法。對於任意一個對象,可以調用它的任意一個方法。這種動態獲取類的信息以及動態調用對象的方法的功能來自於Java 語言的反射(Reflection)機制。

Java 反射機制主要提供了以下功能

在運行時判斷任意一個對象所屬的類。

在運行時構造任意一個類的對象。

在運行時判斷任意一個類所具有的成員變量和方法。

在運行時調用任意一個對象的方法

反射的常用類和函數:Java反射機制的實現要藉助於4個類:Class,Constructor,Field,Method;

其中class代表的是類對象,Constructor-類的構造器對象,Field-類的屬性對象,Method-類的方法對象,通過這四個對象我們可以粗略的看到一個類的各個組成部分。其中最核心的就是Class類,它是實現反射的基礎,它包含的方法我們在第一部分已經進行了基本的闡述。應用反射時我們最關心的一般是一個類的構造器、屬性和方法,下面我們主要介紹Class類中針對這三個元素的方法:

1、得到構造器的方法:在對於學習java的同學們來說看了也不知道怎麼去做的在,在做的過程當中遇到困難可以加扣:五七8接着再來不要斷開0二四後面跟着再來一四4連在一起即可,進行交流同時得到大神的指導和幫助。Constructor getConstructor(Class[] params) — 獲得使用特殊的參數類型的公共構造函數,

Constructor[] getConstructors() — 獲得類的所有公共構造函數

Constructor getDeclaredConstructor(Class[] params) — 獲得使用特定參數類型的構造函數(與接入級別無關)

Constructor[] getDeclaredConstructors() — 獲得類的所有構造函數(與接入級別無關)

2、獲得字段信息的方法

Field getField(String name) — 獲得命名的公共字段

Field[] getFields() — 獲得類的所有公共字段

Field getDeclaredField(String name) — 獲得類聲明的命名的字段

Field[] getDeclaredFields() — 獲得類聲明的所有字段

3、獲得方法信息的方法

Method getMethod(String name, Class[] params) — 使用特定的參數類型,獲得命名的公共方法

Method[] getMethods() — 獲得類的所有公共方法

Method getDeclaredMethod(String name, Class[] params) — 使用特寫的參數類型,獲得類聲明的命名的方法

Method[] getDeclaredMethods() — 獲得類聲明的所有方法

在程序開發中使用反射並結合屬性文件,可以達到程序代碼與配置文件相分離的目的

如果我們想要得到對象的信息,一般需要“引入需要的‘包.類’的名稱–通過new實例化–取得實例化對象”這樣的過程。使用反射就可以變成“實例化對象–getClass()方法–得到完整的‘包.類’名稱”這樣的過程。

正常方法是通過一個類創建對象,反射方法就是通過一個對象找到一個類的信息。

Java Reflection (JAVA反射)機制詳解

反射機制:所謂的反射機制就是java語言在運行時擁有一項自觀的能力。通過這種能力可以徹底的了解自身的情況為下一步的動作做準備。下面具體介紹一下java的反射機制。這裡你將顛覆原來對java的理解。

Java的反射機制的實現要藉助於4個類:class,Constructor,Field,Method;其中class代表的時類對 象,Constructor-類的構造器對象,Field-類的屬性對象,Method-類的方法對象。通過這四個對象我們可以粗略的看到一個類的各個組 成部分。

Class:程序運行時,java運行時系統會對所有的對象進行運行時類型的處理。這項信息記錄了每個對象所屬的類,虛擬機通常使用運行時類型信息選擇正 確的方法來執行(摘自:白皮書)。但是這些信息我們怎麼得到啊,就要藉助於class類對象了啊。在Object類中定義了getClass()方法。我 們可以通過這個方法獲得指定對象的類對象。然後我們通過分析這個對象就可以得到我們要的信息了。

比如:ArrayList arrayList;

Class clazz = arrayList.getClass();

然後我來處理這個對象clazz。

當然了Class類具有很多的方法,這裡重點將和Constructor,Field,Method類有關係的方法。

Reflection 是 Java 程序開發語言的特徵之一,它允許運行中的 Java 程序對自身進行檢查,或者說“自審”,並能直接操作程序的內部屬性。Java 的這一能力在實際應用中也許用得不是很多,但是個人認為要想對java有個更加深入的了解還是應該掌握的。

1.檢測類:

reflection的工作機制

考慮下面這個簡單的例子,讓我們看看 reflection 是如何工作的。

import java.lang.reflect.*;

public class DumpMethods {

public static void main(String args[]) {

try {

Class c = Class.forName(args[0]);

Method m[] = c.getDeclaredMethods();

for (int i = 0; i m.length; i++)

System.out.println(m[i].toString());

} catch (Throwable e) {

System.err.println(e);

}

}

}

按如下語句執行:

java DumpMethods java.util.ArrayList

這個程序使用 Class.forName 載入指定的類,然後調用 getDeclaredMethods 來獲取這個類中定義了的方法列表。java.lang.reflect.Methods 是用來描述某個類中單個方法的一個類。

Java類反射中的主要方法

對於以下三類組件中的任何一類來說 — 構造函數、字段和方法 — java.lang.Class 提供四種獨立的反射調用,以不同的方式來獲得信息。調用都遵循一種標準格式。以下是用於查找構造函數的一組反射調用:

Constructor getConstructor(Class[] params) — 獲得使用特殊的參數類型的公共構造函數,

Constructor[] getConstructors() — 獲得類的所有公共構造函數

Constructor getDeclaredConstructor(Class[] params) — 獲得使用特定參數類型的構造函數(與接入級別無關)

Constructor[] getDeclaredConstructors() — 獲得類的所有構造函數(與接入級別無關)

獲得字段信息的Class 反射調用不同於那些用於接入構造函數的調用,在參數類型數組中使用了字段名:

Field getField(String name) — 獲得命名的公共字段

Field[] getFields() — 獲得類的所有公共字段

Field getDeclaredField(String name) — 獲得類聲明的命名的字段

Field[] getDeclaredFields() — 獲得類聲明的所有字段

用於獲得方法信息函數:

Method getMethod(String name, Class[] params) — 使用特定的參數類型,獲得命名的公共方法

Method[] getMethods() — 獲得類的所有公共方法

Method getDeclaredMethod(String name, Class[] params) — 使用特寫的參數類型,獲得類聲明的命名的方法

Method[] getDeclaredMethods() — 獲得類聲明的所有方法

使用 Reflection:

用於 reflection 的類,如 Method,可以在 java.lang.relfect 包中找到。使用這些類的時候必須要遵循三個步驟:第一步是獲得你想操作的類的 java.lang.Class 對象。在運行中的 Java 程序中,用 java.lang.Class 類來描述類和接口等。

下面就是獲得一個 Class 對象的方法之一:

Class c = Class.forName(“java.lang.String”);

這條語句得到一個 String 類的類對象。還有另一種方法,如下面的語句:

Class c = int.class;

或者

Class c = Integer.TYPE;

它們可獲得基本類型的類信息。其中後一種方法中訪問的是基本類型的封裝類 (如 Intege ) 中預先定義好的 TYPE 字段。

第二步是調用諸如 getDeclaredMethods 的方法,以取得該類中定義的所有方法的列表。

一旦取得這個信息,就可以進行第三步了——使用 reflection API 來操作這些信息,如下面這段代碼:

Class c = Class.forName(“java.lang.String”);

Method m[] = c.getDeclaredMethods();

System.out.println(m[0].toString());

它將以文本方式打印出 String 中定義的第一個方法的原型。

處理對象:

a.創建一個Class對象

b.通過getField 創建一個Field對象

c.調用Field.getXXX(Object)方法(XXX是Int,Float等,如果是對象就省略;Object是指實例).

例如:

import java.lang.reflect.*;

import java.awt.*;

class SampleGet {

public static void main(String[] args) {

Rectangle r = new Rectangle(100, 325);

printHeight(r);

}

static void printHeight(Rectangle r) {

Field heightField;

Integer heightValue;

Class c = r.getClass();

try {

heightField = c.getField(“height”);

heightValue = (Integer) heightField.get(r);

System.out.println(“Height: ” + heightValue.toString());

} catch (NoSuchFieldException e) {

System.out.println(e);

} catch (SecurityException e) {

System.out.println(e);

} catch (IllegalAccessException e) {

System.out.println(e);

}

}

}

安全性和反射:

在處理反射時安全性是一個較複雜的問題。反射經常由框架型代碼使用,由於這一點,我們可能希望框架能夠全面接入代碼,無需考慮常規的接入限制。但是,在其它情況下,不受控制的接入會帶來嚴重的安全性風險,例如當代碼在不值得信任的代碼共享的環境中運行時。

由於這些互相矛盾的需求,Java編程語言定義一種多級別方法來處理反射的安全性。基本模式是對反射實施與應用於源代碼接入相同的限制:

從任意位置到類公共組件的接入

類自身外部無任何到私有組件的接入

受保護和打包(缺省接入)組件的有限接入

不過至少有些時候,圍繞這些限制還有一種簡單的方法。我們可以在我們所寫的類中,擴展一個普通的基本類 java.lang.reflect.AccessibleObject 類。這個類定義了一種setAccessible方法,使我們能夠啟動或關閉對這些類中其中一個類的實例的接入檢測。唯一的問題在於如果使用了安全性管理 器,它將檢測正在關閉接入檢測的代碼是否許可了這樣做。如果未許可,安全性管理器拋出一個例外。

下面是一段程序,在TwoString 類的一個實例上使用反射來顯示安全性正在運行:

public class ReflectSecurity {

public static void main(String[] args) {

try {

TwoString ts = new TwoString(“a”, “b”);

Field field = clas.getDeclaredField(“m_s1”);

// field.setAccessible(true);

System.out.println(“Retrieved value is ” +

field.get(inst));

} catch (Exception ex) {

ex.printStackTrace(System.out);

}

}

}

如果我們編譯這一程序時,不使用任何特定參數直接從命令行運行,它將在field .get(inst)調用中拋出一個IllegalAccessException異常。如果我們不注釋 field.setAccessible(true)代碼行,那麼重新編譯並重新運行該代碼,它將編譯成功。最後,如果我們在命令行添加了JVM參數 -Djava.security.manager以實現安全性管理器,它仍然將不能通過編譯,除非我們定義了ReflectSecurity類的許可權 限。

反射性能:(轉錄別人的啊)

反射是一種強大的工具,但也存在一些不足。一個主要的缺點是對性能有影響。使用反射基本上是一種解釋操作,我們可以告訴JVM,我們希望做什麼並且它滿足我們的要求。這類操作總是慢於只直接執行相同的操作。

下面的程序是字段接入性能測試的一個例子,包括基本的測試方法。每種方法測試字段接入的一種形式 — accessSame 與同一對象的成員字段協作,accessOther 使用可直接接入的另一對象的字段,accessReflection 使用可通過反射接入的另一對象的字段。在每種情況下,方法執行相同的計算 — 循環中簡單的加/乘順序。

程序如下:

public int accessSame(int loops) {

m_value = 0;

for (int index = 0; index loops; index++) {

m_value = (m_value + ADDITIVE_VALUE) *

MULTIPLIER_VALUE;

}

return m_value;

}

public int acces

sReference(int loops) {

TimingClass timing = new TimingClass();

for (int index = 0; index loops; index++) {

timing.m_value = (timing.m_value + ADDITIVE_VALUE) *

MULTIPLIER_VALUE;

}

return timing.m_value;

}

public int accessReflection(int loops) throws Exception {

TimingClass timing = new TimingClass();

try {

Field field = TimingClass.class.

getDeclaredField(“m_value”);

for (int index = 0; index loops; index++) {

int value = (field.getInt(timing) +

ADDITIVE_VALUE) * MULTIPLIER_VALUE;

field.setInt(timing, value);

}

return timing.m_value;

} catch (Exception ex) {

System.out.println(“Error using reflection”);

throw ex;

}

}

在上面的例子中,測試程序重複調用每種方法,使用一個大循環數,從而平均多次調用的時間衡量結果。平均值中不包括每種方法第一次調用的時間,因此初始化時間不是結果中的一個因素。下面的圖清楚的向我們展示了每種方法字段接入的時間:

圖 1:字段接入時間 :

我們可以看出:在前兩副圖中(Sun JVM),使用反射的執行時間超過使用直接接入的1000倍以上。通過比較,IBM JVM可能稍好一些,但反射方法仍舊需要比其它方法長700倍以上的時間。任何JVM上其它兩種方法之間時間方面無任何顯著差異,但IBM JVM幾乎比Sun JVM快一倍。最有可能的是這種差異反映了Sun Hot Spot JVM的專業優化,它在簡單基準方面表現得很糟糕。反射性能是Sun開發1.4 JVM時關注的一個方面,它在反射方法調用結果中顯示。在這類操作的性能方面,Sun 1.4.1 JVM顯示了比1.3.1版本很大的改進。

如果為為創建使用反射的對象編寫了類似的計時測試程序,我們會發現這種情況下的差異不象字段和方法調用情況下那麼顯著。使用newInstance()調 用創建一個簡單的java.lang.Object實例耗用的時間大約是在Sun 1.3.1 JVM上使用new Object()的12倍,是在IBM 1.4.0 JVM的四倍,只是Sun 1.4.1 JVM上的兩部。使用Array.newInstance(type, size)創建一個數組耗用的時間是任何測試的JVM上使用new type[size]的兩倍,隨着數組大小的增加,差異逐步縮小。隨着jdk6.0的推出,反射機制的性能也有了很大的提升。期待中….

總結:

Java語言反射提供一種動態鏈接程序組件的多功能方法。它允許程序創建和控制任何類的對象(根據安全性限制),無需提前硬編碼目標類。這些特性使得反射 特別適用於創建以非常普通的方式與對象協作的庫。例如,反射經常在持續存儲對象為數據庫、XML或其它外部格式的框架中使用。Java reflection 非常有用,它使類和數據結構能按名稱動態檢索相關信息,並允許在運行着的程序中操作這些信息。Java 的這一特性非常強大,並且是其它一些常用語言,如 C、C++、Fortran 或者 Pascal 等都不具備的。

但反射有兩個缺點。第一個是性能問題。用於字段和方法接入時反射要遠慢於直接代碼。性能問題的程度取決於程序中是如何使用反射的。如果它作為程序運行中相 對很少涉及的部分,緩慢的性能將不會是一個問題。即使測試中最壞情況下的計時圖顯示的反射操作只耗用幾微秒。僅反射在性能關鍵的應用的核心邏輯中使用時性 能問題才變得至關重要。

許多應用中更嚴重的一個缺點是使用反射會模糊程序內部實際要發生的事情。程序人員希望在源代碼中看到程序的邏輯,反射等繞過了源代碼的技術會帶來維護問 題。反射代碼比相應的直接代碼更複雜,正如性能比較的代碼實例中看到的一樣。解決這些問題的最佳方案是保守地使用反射——僅在它可以真正增加靈活性的地方 ——記錄其在目標類中的使用。

一下是對應各個部分的例子:

具體的應用:

1、 模仿instanceof 運算符號

class A {}

public class instance1 {

public static void main(String args[])

{

try {

Class cls = Class.forName(“A”);

boolean b1

= cls.isInstance(new Integer(37));

System.out.println(b1);

boolean b2 = cls.isInstance(new A());

System.out.println(b2);

}

catch (Throwable e) {

System.err.println(e);

}

}

}

2、 在類中尋找指定的方法,同時獲取該方法的參數列表,例外和返回值

import java.lang.reflect.*;

public class method1 {

private int f1(

Object p, int x) throws NullPointerException

{

if (p == null)

throw new NullPointerException();

return x;

}

public static void main(String args[])

{

try {

Class cls = Class.forName(“method1”);

Method methlist[]

= cls.getDeclaredMethods();

for (int i = 0; i methlist.length;

i++)

Method m = methlist[i];

System.out.println(“name

= ” + m.getName());

System.out.println(“decl class = ” +

m.getDeclaringClass());

Class pvec[] = m.getParameterTypes();

for (int j = 0; j pvec.length; j++)

System.out.println(“

param #” + j + ” ” + pvec[j]);

Class evec[] = m.getExceptionTypes();

for (int j = 0; j evec.length; j++)

System.out.println(“exc #” + j

+ ” ” + evec[j]);

System.out.println(“return type = ” +

m.getReturnType());

System.out.println(“—–“);

}

}

catch (Throwable e) {

System.err.println(e);

}

}

}

3、 獲取類的構造函數信息,基本上與獲取方法的方式相同

import java.lang.reflect.*;

public class constructor1 {

public constructor1()

{

}

protected constructor1(int i, double d)

{

}

public static void main(String args[])

{

try {

Class cls = Class.forName(“constructor1”);

Constructor ctorlist[]

= cls.getDeclaredConstructors();

for (int i = 0; i ctorlist.length; i++) {

Constructor ct = ctorlist[i];

System.out.println(“name

= ” + ct.getName());

System.out.println(“decl class = ” +

ct.getDeclaringClass());

Class pvec[] = ct.getParameterTypes();

for (int j = 0; j pvec.length; j++)

System.out.println(“param #”

+ j + ” ” + pvec[j]);

Class evec[] = ct.getExceptionTypes();

for (int j = 0; j evec.length; j++)

System.out.println(

“exc #” + j + ” ” + evec[j]);

System.out.println(“—–“);

}

}

catch (Throwable e) {

System.err.println(e);

}

}

}

4、 獲取類中的各個數據成員對象,包括名稱。類型和訪問修飾符號

import java.lang.reflect.*;

public class field1 {

private double d;

public static final int i = 37;

String s = “testing”;

public static void main(String args[])

{

try {

Class cls = Class.forName(“field1”);

Field fieldlist[]

= cls.getDeclaredFields();

for (int i

= 0; i fieldlist.length; i++) {

Field fld = fieldlist[i];

System.out.println(“name

= ” + fld.getName());

System.out.println(“decl class = ” +

fld.getDeclaringClass());

System.out.println(“type

= ” + fld.getType());

int mod = fld.getModifiers();

System.out.println(“modifiers = ” +

Modifier.toString(mod));

System.out.println(“—–“);

}

}

catch (Throwable e) {

System.err.println(e);

}

}

}

5、 通過使用方法的名字調用方法

import java.lang.reflect.*;

public class method2 {

public int add(int a, int b)

{

return a + b;

}

public static void main(String args[])

{

try {

Class cls = Class.forName(“method2”);

Class partypes[] = new Class[2];

partypes[0] = Integer.TYPE;

partypes[1] = Integer.TYPE;

Method meth = cls.getMethod(

“add”, partypes);

method2 methobj = new method2();

Object arglist[] = new Object[2];

arglist[0] = new Integer(37);

arglist[1] = new Integer(47);

Object retobj

= meth.invoke(methobj, arglist);

Integer retval = (Integer)retobj;

System.out.println(retval.intValue());

}

catch (Throwable e) {

System.err.println(e);

}

}

}

6、 創建新的對象

import java.lang.reflect.*;

public class constructor2 {

public constructor2()

{

}

public constructor2(int a, int b)

{

System.out.println(

“a = ” + a + ” b = ” + b);

}

public static void main(String args[])

{

try {

Class cls = Class.forName(“constructor2”);

Class partypes[] = new Class[2];

partypes[0] = Integer.TYPE;

partypes[1] = Integer.TYPE;

Constructor ct

= cls.getConstructor(partypes);

Object arglist[] = new Object[2];

arglist[0] = new Integer(37);

arglist[1] = new Integer(47);

Object retobj = ct.newInstance(arglist);

}

catch (Throwable e) {

System.err.println(e);

}

}

}

7、 變更類實例中的數據的值

import java.lang.reflect.*;

public class field2 {

public double d;

public static void main(String args[])

{

try {

Class cls = Class.forName(“field2”);

Field fld = cls.getField(“d”);

field2 f2obj = new field2();

System.out.println(“d = ” + f2obj.d);

fld.setDouble(f2obj, 12.34);

System.out.println(“d = ” + f2obj.d);

}

catch (Throwable e) {

System.err.println(e);

}

}

}

使用反射創建可重用代碼:

1、 對象工廠

Object factory(String p) {

Class c;

Object o=null;

try {

c = Class.forName(p);// get class def

o = c.newInstance(); // make a new one

} catch (Exception e) {

System.err.println(“Can’t make a ” + p);

}

return o;

}

public class ObjectFoundry {

public static Object factory(String p)

throws ClassNotFoundException,

InstantiationException,

IllegalAccessException {

Class c = Class.forName(p);

Object o = c.newInstance();

return o;

}

}

2、 動態檢測對象的身份,替代instanceof

public static boolean

isKindOf(Object obj, String type)

throws ClassNotFoundException {

// get the class def for obj and type

Class c = obj.getClass();

Class tClass = Class.forName(type);

while ( c!=null ) {

if ( c==tClass ) return true;

c = c.getSuperclass();

}

return false;

}

java反射機制詳解

反射就是把Java的各種成分映射成相應的Java類。

Class類的構造方法是private,由JVM創建。

反射是java語言的一個特性,它允程序在運行時(注意不是編譯的時候)來進行自我檢查並且對內部的成員進行操作。例如它允許一個java的類獲取他所有的成員變量和方法並且顯示出來。Java 的這一能力在實際應用中也許用得不是很多,但是在其它的程序設計語言中根本就不存在這一特性。例如,Pascal、C 或者 C++ 中就沒有辦法在程序中獲得函數定義相關的信息。(來自Sun)

JavaBean 是 reflection 的實際應用之一,它能讓一些工具可視化的操作軟件組件。這些工具通過 reflection 動態的載入並取得 Java 組件(類) 的屬性。

反射是從1.2就有的,後面的三大框架都會用到反射機制,涉及到類”Class”,無法直接new CLass(),其對象是內存里的一份字節碼.

Class 類的實例表示正在運行的 Java 應用程序中的類和接口。枚舉是一種類,注釋是一種接口。每個數組屬於被映射為 Class 對象的一個類,所有具有相同元素類型和維數的數組都共享該 Class 對象。

基本的 Java類型(boolean、byte、char、short、int、long、float 和 double)和關鍵字 void 也表示為 Class 對象。Class 沒有公共構造方法。

Class 對象是在加載類時由 Java 虛擬機以及通過調用類加載器中的 defineClass 方法自動構造的。

Person p1 = new Person();

//下面的這三種方式都可以得到字節碼

CLass c1 = Date.class();

p1.getClass();

//若存在則加載,否則新建,往往使用第三種,類的名字在寫源程序時不需要知道,到運行時再傳遞過來

Class.forName(“java.lang.String”);

Class.forName()字節碼已經加載到java虛擬機中,去得到字節碼;java虛擬機中還沒有生成字節碼 用類加載器進行加載,加載的字節碼緩衝到虛擬機中。 

另外,大家可以關注微信公眾號Java技術棧回復:JVM,獲取我整理的系列JVM教程,都是乾貨。

考慮下面這個簡單的例子,讓我們看看 reflection 是如何工作的。

import java.lang.reflect.*;

public class DumpMethods {

public static void main(String args[]) {

try {

Class c = Class.forName(“java.util.Stack”);

Method m[] = c.getDeclaredMethods();

for (int i = 0; i m.length; i++)

System.out.println(m[i].toString());

}

catch (Throwable e){

System.err.println(e);

}

}

}

public synchronized java.lang.Object java.util.Stack.pop()

public java.lang.Object java.util.Stack.push(java.lang.Object)

public boolean java.util.Stack.empty()

public synchronized java.lang.Object java.util.Stack.peek()

public synchronized int java.util.Stack.search(java.lang.Object)

這樣就列出了java.util.Stack 類的各方法名以及它們的限制符和返回類型。這個程序使用 Class.forName 載入指定的類,然後調用 getDeclaredMethods 來獲取這個類中定義了的方法列表。java.lang.reflect.Methods 是用來描述某個類中單個方法的一個類。

以下示例使用 Class 對象來顯示對象的類名:

void printClassName(Object obj) {

System.out.println(“The class of ” + obj +

” is ” + obj.getClass().getName());

}

還可以使用一個類字面值(JLS Section 15.8.2)來獲取指定類型(或 void)的 Class 對象。例如:

System.out.println(“The name of class Foo is: “+Foo.class.getName());

在沒有對象實例的時候,主要有兩種辦法。

//獲得類類型的兩種方式

Class cls1 = Role.class;

Class cls2 = Class.forName(“yui.Role”);

注意第二種方式中,forName中的參數一定是完整的類名(包名+類名),並且這個方法需要捕獲異常。現在得到cls1就可以創建一個Role類的實例了,利用Class的newInstance方法相當於調用類的默認的構造器。

Object o = cls1.newInstance();

//創建一個實例

//Object o1 = new Role(); //與上面的方法等價

JAVA中反射是什麼

JAVA中反射是動態獲取信息以及動態調用對象方法的一種反射機制。

Java反射就是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意方法和屬性;並且能改變它的屬性。而這也是Java被視為動態語言的一個關鍵性質。

Java反射的功能是在運行時判斷任意一個對象所屬的類,在運行時構造任意一個類的對象,在運行時判斷任意一個類所具有的成員變量和方法,在運行時調用任意一個對象的方法,生成動態代理。

擴展資料:

JAVA中反射實例:

1、Class superClass=clazz.getSuperclass();//獲取父類。

System.out.println(“getSuperclass:”+superClass)。   

2、Class[] interfaces=clazz.getInterfaces();//獲取實現接口。

System.out.println(“getInterfaces:”+interfaces.length)。

3、Constructor[] cons=clazz.getConstructors();//構造方法。

System.out.println(“getConstructors:”+cons.length)。

參考資料來源:百度百科: JAVA反射機制

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/206726.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-08 14:16
下一篇 2024-12-08 14:17

相關推薦

  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java Bean加載過程

    Java Bean加載過程涉及到類加載器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean加載的過程。 一、類加載器 類加載器是Java虛擬機…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Java判斷字符串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字符串中是否存在多個指定字符: 一、字符串遍歷 字符串是Java編程中非常重要的一種數據類型。要判斷字符串中是否存在多個指定字符…

    編程 2025-04-29
  • VSCode為什麼無法運行Java

    解答:VSCode無法運行Java是因為默認情況下,VSCode並沒有集成Java運行環境,需要手動添加Java運行環境或安裝相關插件才能實現Java代碼的編寫、調試和運行。 一、…

    編程 2025-04-29
  • Java任務下發回滾系統的設計與實現

    本文將介紹一個Java任務下發回滾系統的設計與實現。該系統可以用於執行複雜的任務,包括可回滾的任務,及時恢復任務失敗前的狀態。系統使用Java語言進行開發,可以支持多種類型的任務。…

    編程 2025-04-29
  • Java 8 Group By 會影響排序嗎?

    是的,Java 8中的Group By會對排序產生影響。本文將從多個方面探討Group By對排序的影響。 一、Group By的概述 Group By是SQL中的一種常見操作,它…

    編程 2025-04-29

發表回復

登錄後才能評論