首頁 Java java教程 Java基礎入門之反射

Java基礎入門之反射

Jul 20, 2017 pm 01:09 PM
java 反射 基礎

今天學到Java基礎中的反反射。依照我學習後的個人理解呢,反射就是一套取得類別、屬性、方法等的工具吧。 (其實,感覺學完反射後,有點像喝涼水,解渴但確實我也沒體會出它有什麼味道,我可能沒有學到精髓吧。自己都能感覺少點什麼。這是我Java基礎學習的最後一個部分了,我想再複習一遍,然後再學習其他的。 )

在學習反射之前,我先回憶了一下可變參數。

public static void main(String[] args) {
            test();//调用方法1test("JAVA");//调用方法2test("JAVA","工程师");//调用方法3test(new String[]{"水果","电器"});//调用方法4        }    static void test(String ... array){  //直接打印:System.out.println(array);for(String str:array){  //利用增强for遍历            System.out.println(str);
            }
        }
登入後複製

之所以回憶可變參數呢,是因為它與反射的應用有點像。如果將一個方法定義為可變參數,在呼叫的時候傳參的限制就少了一大截。在反射當中呢,我們利用一些方法,得到類別的實例對象,那麼類別裡面的方法、屬性等,就盡收眼底。在前面的學習中知道了,方法、屬性等都有靜態的和非靜態的,私有的和非私有的之分,那麼我們在調用的時候,想取哪一塊,或者說只想取得哪一塊,是不是也可以想個辦法實現呢?這時候,反射就出現了,現今我對它的理解就只有這些了。繼續努力吧。

一、反射的概念

JAVA反射機制是在運行狀態中(注意不是編譯的時候),對於任意一個類別,都能夠知道這個類別的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法;這種動態獲取的資訊以及動態調用對象的方法的功能稱為java語言的反射機制。

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

-- 在執行階段判斷任意一個物件所屬的類別;

-- 在執行時建構任一個類別的物件;

-- 在執行時判斷任一類別所具有的成員變數與方法;

-- 在執行時呼叫任意一個物件的方法;

- - 產生動態代理。

JDK中,與反射相關的類別,主要有以下幾個

//java.lang套件下

Class 類別

Class 類別的實例表示正在執行的Java 應用程式中的類別和介面。枚舉是一種類,註解是一種介面。每個數組屬於被映射為 Class 物件的一個類,所有具有相同元素類型和維數的數組都共用該 Class 物件。基本的 Java 類型(boolean、byte、char、short、int、long、float 和 double)    和關鍵字 void 也表示為 Class 物件。

關於Class類別JDK裡面的解釋:

public finalclass Class<T> implements java.io.Serializable,
                              java.lang.reflect.GenericDeclaration,
                              java.lang.reflect.Type,
                              java.lang.reflect.AnnotatedElement {private static final int ANNOTATION= 0x00002000;private static final int ENUM      = 0x00004000;private static final int SYNTHETIC = 0x00001000;private static native void registerNatives();static {
        registerNatives();
    }/* * Constructor. Only the Java Virtual Machine creates Class
     * objects.     */private Class() {}
登入後複製

Class類別JDK裡的一些方法(個人覺得讀起來很舒服,自己想記錄)

public String toString() {return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))+ getName();
    }//应该是三元表达式
登入後複製
public static Class<?> forName(String className)throws ClassNotFoundException {
        Class<?> caller = Reflection.getCallerClass();return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }
登入後複製
public static Class<?> forName(String name, boolean initialize,
                                   ClassLoader loader)throws ClassNotFoundException
    {
        Class<?> caller = null;
        SecurityManager sm = System.getSecurityManager();if (sm != null) {// Reflective call to get caller class is only needed if a security manager// is present.  Avoid the overhead of making this call otherwise.caller = Reflection.getCallerClass();if (loader == null) {
                ClassLoader ccl = ClassLoader.getClassLoader(caller);if (ccl != null) {
                    sm.checkPermission(
                        SecurityConstants.GET_CLASSLOADER_PERMISSION);
                }
            }
        }return forName0(name, initialize, loader, caller);
    }
登入後複製
private static native Class<?> forName0(String name, boolean initialize,
                                            ClassLoader loader,
                                            Class<?> caller)throws ClassNotFoundException;
登入後複製
public T newInstance()throws InstantiationException, IllegalAccessException
    {if (System.getSecurityManager() != null) {
            checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
        }// NOTE: the following code may not be strictly correct under// the current Java memory model.// Constructor lookupif (cachedConstructor == null) {if (this == Class.class) {throw new IllegalAccessException("Can not call newInstance() on the Class for java.lang.Class");
            }try {
                Class<?>[] empty = {};final Constructor<T> c = getConstructor0(empty, Member.DECLARED);// Disable accessibility checks on the constructor// since we have to do the security check here anyway// (the stack depth is wrong for the Constructor's// security check to work)                java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() {public Void run() {
                                c.setAccessible(true);return null;
                            }
                        });
                cachedConstructor = c;
            } catch (NoSuchMethodException e) {throw new InstantiationException(getName());
            }
        }
        Constructor<T> tmpConstructor = cachedConstructor;// Security check (same as in java.lang.reflect.Constructor)int modifiers = tmpConstructor.getModifiers();if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
            Class<?> caller = Reflection.getCallerClass();if (newInstanceCallerCache != caller) {
                Reflection.ensureMemberAccess(caller, this, null, modifiers);
                newInstanceCallerCache = caller;
            }
        }// Run constructortry {return tmpConstructor.newInstance((Object[])null);
        } catch (InvocationTargetException e) {
            Unsafe.getUnsafe().throwException(e.getTargetException());// Not reachedreturn null;
        }
    }
登入後複製
public String getName() {
        String name = this.name;if (name == null)this.name = name = getName0();return name;
    }
登入後複製
#
// cache the name to reduce the number of calls into the VMprivate transient String name;private native String getName0();
登入後複製

還有很多,暫不記錄了。 。 。 。 。

//java.lang.reflect  包下
Constructor 代表构造函数
Method 代表方法
Field 代表字段
Array 与数组相关
登入後複製

二、Class類別的說明

常用的得到Class类的方法 // Class c=new Class(); 不可以,因为它被私有化了1) Class c=Student.class;   //用类名.class 就可以得到Class类的实例2) Student stu=new Student();
Class c=stu.getClass();   //用对象名.getClass();3) Class c=Class.forName("com.mysql.jdbc.Driver");
登入後複製
//例一  通过调用无参的构造函数,创建类对象public class Test {public static void main(String[] args) throws InstantiationException, IllegalAccessException {
    Class clazz=Dog.class;
    Dog dog=(Dog)clazz.newInstance();
    dog.shout();
    }
}            
class Dog{void shout(){
    System.out.println("汪汪");
    }
}
登入後複製

透過例一,我並沒有看出來利用反射的好處,呃~~

//例二 上例的改写Class clazz=Class.forName("com.weiboo.Dog"); //注意,必须是类的全部Dog dog=(Dog)clazz.newInstance();
dog.shout();
登入後複製
//例三  (运行本类,Dog 和 Cat 类,必须有一个无参的构造函数)public class Test {public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    Dog dog=(Dog)createObj(Dog.class);
    dog.shout();
                
    Cat cat=(Cat)createObj(Cat.class);
    cat.speak();
    }                    
static Object createObj(Class clazz) throws InstantiationException, IllegalAccessException{return clazz.newInstance();  //调用的是newInstance() 方法创建的类对象,它调用的是类中无参的构造方法}
    }        
class Dog{void shout(){
    System.out.println("汪汪");
    }
}        
class  Cat{void speak(){
    System.out.println("喵~~~");        
    }
}
登入後複製

三、反射中的其他的類別的說明

1) Constructor

代表類別中的建構子     Class 類別提供了下列四個方法

public Constructor[] getConstructors()      //傳回類別中所有的public建構器集合,預設建構器的下標為0

public Constructor getConstructor(Class... parameterTypes)   //傳回指定public建構器,參數為建構器參數類型集合

public Constructor[] getDeclaredConstructors()  //傳回類別中所有的建構器,包含私有的

public Constructor getDeclaredConstructor(Class ... parameterTypes) //傳回任意指定的建構器,包含私有的

import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;//例子 得到某个类中指定的某个构造函数所对应的 Constructor对象class Test2 {public static void main(String[] args) throws InstantiationException,
            IllegalAccessException, ClassNotFoundException,
            NoSuchMethodException, SecurityException, IllegalArgumentException,
            InvocationTargetException {
        Class<Cat> clazz = Cat.class;

        Constructor<Cat> c = clazz.getConstructor(int.class, String.class);
        Cat cat = (Cat) c.newInstance(20, "加飞猫");
        cat.speak();
    }class Cat {private String name;private int age;public Cat(int age, String name) {this.age = age;this.name = name;
        }public Cat(String content) {
            System.out.println("这是构造函数得到的参数" + content);
        }void speak() {
            System.out.println("喵~~~");
            System.out.println("我的名字是" + this.name + "我的年龄是" + this.age);
        }
    }
}
登入後複製
#
/例子 访问类中的私有构造函数
Class clazz=Cat.class;
Constructor c=clazz.getDeclaredConstructor();
c.setAccessible(true);  //让私有成员可以对外访问Cat cat=(Cat) c.newInstance();  //对于私有的来说,能不能行?cat.speak();
登入後複製

2) Method 代表類別中的方法

Class 類別提供了以下四個方法

public Method[] getMethods()    //取得所有的共有方法的集合,包擴充繼承的

#public Method getMethod(String name,Class... parameterTypes) // 取得指定公有方法參數1:方法名稱參數2:參數型別集 

public Method[] getDeclaredMethods()  //取得所有的方法(包擴充私有的),除了繼承來的

public Method getDeclaredMethod(String name,Class... parameterTypes) //取得任意指定方法,除來了繼承來的

//调用类中的私有方法main 函数
Class  clazz=Cat.class;//调用一个不带参数的方法Method m=clazz.getDeclaredMethod("speak");
m.setAccessible(true);
Cat c=new Cat();
m.invoke(c);  //让方法执行                
                    
//调用一个带参数的方法Method m=clazz.getDeclaredMethod("eat", int.class,String.class);
m.setAccessible(true);
Cat c=new Cat();
m.invoke(c, 20,"鱼");    

class  Cat{private String name;private int age;
                        
Cat(){    
}public Cat(int age,String name){this.age=age;this. name=name;
    }                        
public Cat(String content){
    System.out.println("这是构造函数得到的参数"+content);
    }                        private void speak(){
    System.out.println("喵~~~");        
    System.out.println("我的名字是"+this.name+"我的年龄是"+this.age);
    }                        private void eat(int time,String something){
    System.out.println("我在"+time +"分钟内吃了一个"+something);
    }
}
登入後複製
例子 查看一个类中的所有的方法名public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
    Class  clazz=Cat.class;                        /*Method []  methodList=clazz.getMethods() ; //查看所有的公有方法,包扩继承的
    for(Method m:methodList){
    System.out.println(m.getName());
    }*/Method []  methodList=clazz.getDeclaredMethods(); //查看所有的方法,包扩私有的,但不包扩继承的for(Method m:methodList){
    System.out.println(m.getName());
    }
}
登入後複製

3) Field 代表字段

public Field getDeclaredField(String name)  // 获取任意指定名字的成员

public Field[] getDeclaredFields()  // 获取所有的成员变量,除了继承来的

public Field getField(String name)  // 获取任意public成员变量,包含继承来的

public Field[] getFields() // 获取所有的public成员变量

//例子 访问字段public class Test {public static void main(String[] args) throws Exception {
    Class clazz=Cat.class;                         /* Field field= clazz.getField("home");
    Cat c=new Cat();
    Object obj=field.get(c);
    System.out.println(obj); // 家*/ 
    Cat cat=new Cat();
    Field  [] fieldList= clazz.getDeclaredFields();for(Field f:fieldList){  //访问所有字段f.setAccessible(true);
    System.out.println(f.get(cat)); 
                                   }
        }
}                            
class  Cat{private String name="黑猫";private int age=2;public String home="家";
}
登入後複製

四、反射的应用

用一个例子来说明一下,比较两个同类对象中的所有字段,不同的并把它输出来。

import java.lang.reflect.Field;import java.util.HashMap;import java.util.Map;public class Test {public static void main(String[] args) throws Exception {
        Student stu1 = new Student(24, "李磊", "工程大学", "女");
        Student stu2 = new Student(20, "王一", "师大", "男");
        Map<String, String> map = compare(stu1, stu2);for (Map.Entry<String, String> item : map.entrySet()) {
            System.out.println(item.getKey() + ":" + item.getValue());
        }
    }static Map<String, String> compare(Student stu1, Student stu2) {
        Map<String, String> resultMap = new HashMap<String, String>();

        Field[] fieldLis = stu1.getClass().getDeclaredFields(); // 得到stu1所有的字段对象try {for (Field f : fieldLis) {
                f.setAccessible(true); // 别忘了,让私有成员可以对外访问Object v1 = f.get(stu1);
                Object v2 = f.get(stu2);if (!(v1.equals(v2))) {
                    resultMap.put(f.getName(), "stu1的值是" + v1 + "   stu2的值是"
                            + v2);
                }
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }return resultMap;

    }

}class Student {private String name;private String school;private String sex;public Student(int age, String name, String school, String sex) {this.age = age;this.name = name;this.school = school;this.sex = sex;
    }private int age;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;
    }public String getSchool() {return school;
    }public void setSchool(String school) {this.school = school;
    }public String getSex() {return sex;
    }public void setSex(String sex) {this.sex = sex;
    }
}
登入後複製

以上是Java基礎入門之反射的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Java 中的完美數 Java 中的完美數 Aug 30, 2024 pm 04:28 PM

Java 完美數指南。這裡我們討論定義,如何在 Java 中檢查完美數?

Java 中的隨機數產生器 Java 中的隨機數產生器 Aug 30, 2024 pm 04:27 PM

Java 隨機數產生器指南。在這裡,我們透過範例討論 Java 中的函數,並透過範例討論兩個不同的生成器。

Java中的Weka Java中的Weka Aug 30, 2024 pm 04:28 PM

Java 版 Weka 指南。這裡我們透過範例討論簡介、如何使用 weka java、平台類型和優點。

Java 中的史密斯數 Java 中的史密斯數 Aug 30, 2024 pm 04:28 PM

Java 史密斯數指南。這裡我們討論定義,如何在Java中檢查史密斯號?帶有程式碼實現的範例。

Java Spring 面試題 Java Spring 面試題 Aug 30, 2024 pm 04:29 PM

在本文中,我們保留了最常被問到的 Java Spring 面試問題及其詳細答案。這樣你就可以順利通過面試。

突破或從Java 8流返回? 突破或從Java 8流返回? Feb 07, 2025 pm 12:09 PM

Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

Java 中的時間戳至今 Java 中的時間戳至今 Aug 30, 2024 pm 04:28 PM

Java 中的時間戳記到日期指南。這裡我們也結合範例討論了介紹以及如何在java中將時間戳記轉換為日期。

Java程序查找膠囊的體積 Java程序查找膠囊的體積 Feb 07, 2025 am 11:37 AM

膠囊是一種三維幾何圖形,由一個圓柱體和兩端各一個半球體組成。膠囊的體積可以通過將圓柱體的體積和兩端半球體的體積相加來計算。本教程將討論如何使用不同的方法在Java中計算給定膠囊的體積。 膠囊體積公式 膠囊體積的公式如下: 膠囊體積 = 圓柱體體積 兩個半球體體積 其中, r: 半球體的半徑。 h: 圓柱體的高度(不包括半球體)。 例子 1 輸入 半徑 = 5 單位 高度 = 10 單位 輸出 體積 = 1570.8 立方單位 解釋 使用公式計算體積: 體積 = π × r2 × h (4

See all articles