国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java 基礎進階篇(十七):反射概述及獲取對象的方式

這篇具有很好參考價值的文章主要介紹了Java 基礎進階篇(十七):反射概述及獲取對象的方式。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。


一、反射概述

反射是指對于任何一個Class類,在 “運行的時候”,不用創(chuàng)建對象,就可以直接得到這個類全部成分。

  • 在運行時,可以直接得到這個類的構造器對象:Constructor
  • 在運行時,可以直接得到這個類的成員變量對象:Field
  • 在運行時,可以直接得到這個類的成員方法對象:Method

這種運行時動態(tài)獲取類信息以及動態(tài)調(diào)用類中成分的能力稱為 Java 語言的反射機制。

反射的作用:反射是在運行時獲取類的字節(jié)碼文件對象,然后可以解析類中的全部成分。
反射的關鍵:反射的第一步都是先得到編譯后的 Class 類對象,然后就可以得到 Class 的全部成分。

java反射獲取對象,JavaSE,java,開發(fā)語言,反射

注意:“類對象”和“類的對象”之間的區(qū)別,“類的對象”是 new 出來對象,而“類對象”是其本身,即 class 文件,是“類”類型。


二、反射獲取類對象

反射的第一步:獲取 Class 類的對象。

java反射獲取對象,JavaSE,java,開發(fā)語言,反射

java反射獲取對象,JavaSE,java,開發(fā)語言,反射

三種方式:

Class c1 = Class.forName(“全類名");
Class c2 = 類名.class;
Class c3 = 對象.getClass();

舉例:

public class Test {
    public static void main(String[] args) throws Exception {
        // 1、Class類中的一個靜態(tài)方法:forName(全限名:包名 + 類名)
        Class c = Class.forName("com.itheima.d2_reflect_class.Student");
        System.out.println(c); // Student.class

        // 2、類名.class
        Class c1 = Student.class;
        System.out.println(c1);

        // 3、對象.getClass() 獲取對象對應類的Class對象。
        Student s = new Student();
        Class c2 = s.getClass();
        System.out.println(c2);
    }
}

三、反射獲取構造器對象

步驟:

java反射獲取對象,JavaSE,java,開發(fā)語言,反射
獲取構造器的方法:
java反射獲取對象,JavaSE,java,開發(fā)語言,反射

Constructor類中用于創(chuàng)建對象的方法:
java反射獲取對象,JavaSE,java,開發(fā)語言,反射

注:反射可以破壞封裝性,私有的也可以執(zhí)行了。

舉例:

public class Student {
	private String name;
	private int age;
	
	// 構造器私有化
	private Student(){
	    System.out.println("無參數(shù)構造器執(zhí)行!");
	}
	
	public Student(String name, int age) {
	    System.out.println("有參數(shù)構造器執(zhí)行!");
	    this.name = name;
	    this.age = age;
	}
	...
}
@Test
public void getDeclaredConstructor() throws NoSuchMethodException {
	// 1. 第一步:獲取類對象
	Class c = Student.class;
	
	// 2. 定位單個構造器對象 (按照參數(shù)定位到無參構造器)
	Constructor con = c.getDeclaredConstructor();
	System.out.println(con.getName() + " ==> " + con.getParameterCount()); // Student.class ==> 0
	
	// 3. 定位單個構造器對象 (按照參數(shù)定位到有參構造器)
	Constructor con1 = c.getDeclaredConstructor(String.class, int.class);
	System.out.println(con1.getName() + " ==> " + con1.getParameterCount()); // Student.class ==> 2
}

@Test
public void getDeclaredConstructors(){
    // 1. 第一步:獲取類對象
    Class c = Student.class;
    
    // 2. 提取類中的全部構造方法
    Constructor[] constructors = c.getDeclaredConstructors();
    
    // 3. 遍歷構造器
    // 拿到所有的構造器
    for (Constructor con : constructors) {
        System.out.println(con.getName() + " ==> " + con.getParameterCount());
    }
}

暴力反射舉例:

@Test
public void getDeclaredConstructor() throws Exception {
	// 1. 第一步:獲取類對象
	Class c = Student.class;
	
	// 2. 定位單個構造器對象 (按照參數(shù)定位到無參構造器)
	Constructor con = c.getDeclaredConstructor();
	
	// 遇到私有的構造器對象,可以暴力反射
	con.setAccessible(true);
	Student student = (Student) con.newInstance();
	System.out.println(student); // Student{name='null', age=0}
}

四、反射獲取成員變量對象

步驟:
java反射獲取對象,JavaSE,java,開發(fā)語言,反射

反射的第一步是先得到類對象,然后從類對象中獲取類的成分對象。

Class類中用于獲取成員變量的方法:
java反射獲取對象,JavaSE,java,開發(fā)語言,反射

Field類中用于取值、賦值的方法:
java反射獲取對象,JavaSE,java,開發(fā)語言,反射
注:某成員變量是非public的,需要打開權限(暴力反射),然后再取值、賦值。

舉例:

public class Student {
    private String name;
    private int age;
    public static String schoolName;
    public static final String  COUNTTRY = "中國";
	....
}
@Test
public void getDeclaredField() throws Exception {
	// 1. 第一步:獲取類對象
	Class c = Student.class;
	
	// 2. 第二步:根據(jù)名稱定位某個成員變量
	Field f = c.getDeclaredField("age");
	System.out.println(f.getName() +" ===> " + f.getType()); // age ===> int
}
 
@Test
public void getDeclaredFields(){
	// 1. 第一步:獲取類對象
	Class c = Student.class;
	
	// 2. 第二步:根據(jù)名稱定位某個成員變量
	Field[] fields = c.getDeclaredFields();
	
	// 3. 第三步:遍歷
	for (Field field : fields) {
		System.out.println(field.getName() + " ==> " + field.getType());
		// name ==> class java.lang.String ...
	}
}

暴力反射舉例:

@Test
public void setField() throws Exception {
	// 1. 第一步:反射第一步,獲取類對象
	Class c = Student.class;
	
	// 2. 第二步:提取某個成員變量
	Field ageF = c.getDeclaredField("age");
	ageF.setAccessible(true); // 暴力打開權限
	
	// 3. 第三步:賦值
	Student s = new Student();
	ageF.set(s, 18);  // 相當于 s.setAge(18);
	System.out.println(s);
	
	// 4. 第四步:取值
	int age = (int) ageF.get(s);
	System.out.println(age);
}

五、反射獲取方法對象

步驟:
java反射獲取對象,JavaSE,java,開發(fā)語言,反射

獲取成員方法的方法:
java反射獲取對象,JavaSE,java,開發(fā)語言,反射

Method類中用于觸發(fā)執(zhí)行的方法:
java反射獲取對象,JavaSE,java,開發(fā)語言,反射
注:某成員方法是非 public 的,需要打開權限(暴力反射),然后再取值、賦值。

舉例:

public class Dog {
    public void run(){
        System.out.println("狗跑的賊快~~");
    }
    private void eat(){
        System.out.println("狗吃骨頭");
    }
    private String eat(String name){
        System.out.println("狗吃" + name);
        return "吃的很開心!";
    }
    public static void sleep(){
        System.out.println("狗在睡覺!");
    }
}
@Test
public void getDeclaredMethods(){
	// 1. 第一步:獲取類對象
	Class c = Dog.class;
	
	// 2. 第二步:提取全部方法;包括私有的
	Method[] methods = c.getDeclaredMethods();
	
	// 3. 第三步:遍歷全部方法
	for (Method method : methods) {
	    System.out.println(method.getName() +" 返回值類型:" 
	            + method.getReturnType() + " 參數(shù)個數(shù):" + method.getParameterCount());
	}
	// getName 返回值類型:String 參數(shù)個數(shù):0 ...
}

暴力反射舉例:

@Test
public void getDeclaredMethod() throws Exception {
	// 1. 第一步:獲取類對象
	Class c = Dog.class;
	
	// 2. 第二步:提取單個方法對象
	Method eat = c.getDeclaredMethod("eat");
	Method eat2 = c.getDeclaredMethod("eat", String.class);
	
	// 暴力打開權限了
	eat.setAccessible(true);
	eat2.setAccessible(true);
	
	// 3. 第三步: 觸發(fā)方法的執(zhí)行
	Dog d = new Dog();
	// 注意:方法如果是沒有返回值,那么返回的是null。
	Object result = eat.invoke(d); // 狗吃骨頭
	System.out.println(result); // null
	
	Object result2 = eat2.invoke(d, "骨頭"); // 狗吃骨頭
	System.out.println(result2); // 吃的很開心!
}

六、 反射的作用

6.1 繞過編譯階段為集合添加數(shù)據(jù)

繞過泛型約束:泛型只是在編譯階段可以約束集合只能操作某種數(shù)據(jù)類型,編譯成Class文件后,進入運行階段的時候,泛型會自動擦除。

反射是作用在運行時的技術,此時集合的泛型將不能產(chǎn)生約束了,此時是可以為集合存入其他任意類型的元素。

舉例:

public class Test {
	public static void main(String[] args) throws Exception {
        // 需求:反射實現(xiàn)泛型擦除后,加入其他類型的元素
        ArrayList<String> lists1 = new ArrayList<>();
        ArrayList<Integer> lists2 = new ArrayList<>();
        System.out.println(lists1.getClass() ==  lists2.getClass());  // true  ArrayList.class

        ArrayList<Integer> lists3 = new ArrayList<>();
        lists3.add(23);
        lists3.add(22);
        // lists3.add("黑馬"); // 報錯

        Class c = lists3.getClass(); // ArrayList.class  ===> public boolean add(E e)
        // 定位類對象 c 中的 add 方法
        Method add = c.getDeclaredMethod("add", Object.class); // 第二個參數(shù)代表此時 add方法中參數(shù)是任意類型
        boolean rs = (boolean) add.invoke(lists3, "黑馬");
        System.out.println(rs); // true
        System.out.println(lists3); // [23, 22, 黑馬]
	}
}

舉例2:變量被賦值后,泛型也會被擦除

public class Test2 {
    public static void main(String[] args) {
        // 需求:反射實現(xiàn)泛型擦除后,加入其他類型的元素
        ArrayList<Integer> list1 = new ArrayList<>();
        list1.add(23);
        list1.add(22);
        // list.add("黑馬"); // 報錯

        ArrayList list2 = list1;
        list2.add("白馬");
        list2.add(false);
        System.out.println(list2);  // [23, 22, 白馬, false]
    }
}

6.2 通用框架的底層原理

需求:給定任意一個對象,在不清楚對象字段的情況可以,可以把對象的字段名稱和對應值存儲到文件中去。

public class MyBatisUtil {
    /**
     * 保存任意類型的對象
     */
    public static void save(Object obj){
        try (
                PrintStream ps = new PrintStream(new FileOutputStream("day11-oop/src/data.txt", true));
                ){
            // 提取到這個對象的全部成員變量,只有反射可以解決
            Class c = obj.getClass();  //   c.getSimpleName() 獲取當前類名   c.getName() 獲取全限名:包名+類名
            ps.println("================" + c.getSimpleName() + "================");

            // 提取到它全部成員變量
            Field[] fields = c.getDeclaredFields();

            // 獲取成員變量的信息
            for (Field field : fields) {
                field.setAccessible(true);
                String name = field.getName();
                String value = field.get(obj) + "";
                ps.println(name + " ==> " + value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
public class Test {
    public static void main(String[] args) {
        Student s = new Student();
        s.setName("豬八戒");
        s.setClassName("西天跑路1班");
        s.setAge(1000);
        s.setHobby("吃,睡");
        s.setSex('男');
        MyBatisUtil.save(s);

        Teacher t = new Teacher();
        t.setName("波仔");
        t.setSex('男');
        t.setSalary(6000);
        MyBatisUtil.save(t);
    }
}

測試結果:

java反射獲取對象,JavaSE,java,開發(fā)語言,反射


文章參考:Java入門基礎視頻教程,java零基礎自學就選黑馬程序員Java入門教程(含Java項目和Java真題)文章來源地址http://www.zghlxwxcb.cn/news/detail-730429.html

到了這里,關于Java 基礎進階篇(十七):反射概述及獲取對象的方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • Java反射:探索對象創(chuàng)建與類信息獲取

    Java反射:探索對象創(chuàng)建與類信息獲取

    ??歡迎來到Java學習路線專欄~Java反射:探索對象創(chuàng)建與類信息獲取 ☆* o(≧▽≦)o *☆嗨~我是IT·陳寒?? ?博客主頁:IT·陳寒的博客 ??該系列文章專欄:Java學習路線 ??其他專欄:Java學習路線 Java面試技巧 Java實戰(zhàn)項目 AIGC人工智能 數(shù)據(jù)結構學習 ??文章作者技術和水平有限

    2024年02月09日
    瀏覽(24)
  • 【Java反射】反射獲取Class、Constructor、Field、Method的方式

    如下是相應的獲取方式 總結: 首先獲取對象的Class,然后通過getXXX方法獲取,帶Declared可以通過setAccessible獲取私有XXX

    2024年02月02日
    瀏覽(26)
  • 【Java 基礎篇】Java反射:深入了解Class對象

    【Java 基礎篇】Java反射:深入了解Class對象

    Java是一門強類型語言,它要求在編譯時知道所有的類和對象類型。然而,有時候我們需要在運行時動態(tài)地獲取和操作類的信息,這就是Java反射的用武之地。本文將深入探討Java反射,特別是與Class對象相關的內(nèi)容。 反射是一種機制,允許我們在運行時檢查、獲取和操作類的信

    2024年02月06日
    瀏覽(24)
  • Java SE 學習筆記(十七)—— 單元測試、反射

    Java SE 學習筆記(十七)—— 單元測試、反射

    開發(fā)好的系統(tǒng)中存在很多方法,如何對這些方法進行測試? 以前我們都是將代碼全部寫完再進行測試。其實這樣并不是很好。在以后工作的時候,都是寫完一部分代碼,就測試一部分。這樣,代碼中的問題可以得到及時修復。也避免了由于代碼過多,從而無法準確定位到錯誤

    2024年02月06日
    瀏覽(24)
  • 【Java 進階篇】Java Request 獲取請求參數(shù)的通用方式詳解

    【Java 進階篇】Java Request 獲取請求參數(shù)的通用方式詳解

    在Java Web開發(fā)中,獲取HTTP請求的參數(shù)是一項基本任務。請求參數(shù)可以包含在URL中,也可以包含在請求體中,例如表單提交時的參數(shù)。在Java中,可以使用 HttpServletRequest 對象來獲取HTTP請求的參數(shù)。本文將詳細解釋如何使用Java獲取HTTP請求的參數(shù),包括通用的方式以及示例代碼。

    2024年02月05日
    瀏覽(35)
  • Java list 根據(jù)id獲取對象 有哪幾種方式

    在 Java 中,有以下幾種方法來根據(jù) ID 獲取列表中的對象: 循環(huán)遍歷列表:遍歷整個列表,比較每個對象的 ID 和目標 ID,如果匹配,就返回該對象。 使用 Stream API:使用 Java 8 的 Stream API 操作列表,并使用 filter() 方法篩選出具有指定 ID 的對象。 使用 Map:將對象存儲在 Map 中

    2024年02月11日
    瀏覽(23)
  • java基礎入門-05-【面向?qū)ο筮M階(static&繼承)】

    java基礎入門-05-【面向?qū)ο筮M階(static&繼承)】

    類的定義格式如下: 例如: 例如: 1.3.1 封裝的步驟 1.使用 private 來修飾成員變量。 2.使用 public 修飾getter和setter方法。 1.3.2 封裝的步驟實現(xiàn) private修飾成員變量 public修飾getter和setter方法 1.4.1 構造方法的作用 在創(chuàng)建對象的時候,給成員變量進行初始化。 初始化即賦值的意

    2024年02月03日
    瀏覽(24)
  • GO基礎進階篇 (十二)、反射

    Go語言中的反射是指在程序運行時檢查程序的結構,比如變量的類型、方法的簽名等。Go語言的反射包是reflect。通過反射,你可以動態(tài)地檢查類型信息、獲取字段和方法、調(diào)用方法等。 反射可以在運行時動態(tài)獲取變量的各種信息,比如變量的類型、值等 如果是結構體,還可以

    2024年02月02日
    瀏覽(53)
  • java通過反射創(chuàng)建反射對象三種的方法

    目錄 前言: 代碼部分: computer類: 1.類名.class創(chuàng)建反射對象: 2.對象.getclass創(chuàng)建反射對象: 3.Class.forName(\\\"\\\")創(chuàng)建反射對象: JAVA反射機制是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調(diào)用它的任意方法和屬性;這種動態(tài)

    2024年02月14日
    瀏覽(30)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包