src==> 源檔案存放位置
bin==> bean 檔案
_____________________________________________________________
=============================================================
++++++++++++++++++++++++ 反射 筆記 +++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
_____________________________________________________________
-->
面向對象: 萬物皆對象
--> java類 : 類的組成部分
( 1 )每個類都有一個package
( 2 )每個類有一個類名
( 3 )構造方法
( 4 )屬性
( 5 )普通方法
....... 靜态方法 未包括
=============================================================
---> 反射的根基 : java 開發者為我們提供了一個類來描述 java 檔案 ,這個類為Class
同時,Class 類型對應的對象可以代表某一個某一個類的位元組碼檔案
public class Class {
......
}
對象代表位元組碼檔案
位元組碼檔案類型 ===> . class
==================================
---> 如何擷取某一類的位元組碼檔案? ====> 擷取一個類的對象
--------------------------------------------------------
[ 注: 反射不能 new 出來 , 沒有 new ]
三種方式擷取:
--> 通過類名.class
--> 類名.forName("某個類的全路徑")
--> 對象名 .getClass( ) [ - 點不能丢 - ]
---------------------------------------------------------
@Test //擷取User的位元組碼檔案
public void ReflectionTest1() throws ClassNotFoundException {
//通過類名擷取位元組碼檔案
Class userClass = User.class; <---------- 第一種
//通過.forName擷取位元組碼檔案
Class u = Class.forName("User"); <---------- 第二種
//通過.getClass 擷取
User user = new User();
Class get = user.getClass(); <---------- 第三種
//以上三者擷取的是同一個位元組碼檔案 , sout 輸出 true
// 注意 第三種擷取的方式需要執行個體化對象,通過對象的.getClass方法擷取
System.out.println(u==userClass);
System.out.println(u==get);
}
----------------------------------------------------------
所有類的底層都是位元組碼===> 二進制檔案
----------------------------------------------------------
* 通過反射建立對象
* 所謂的反射,将一個類中的 各個成員 映射 成 相對應的 java類型
* ==================================================================
* 各個成員: 包括 { 包 --> package, 構造器 ---> Contructor , 屬性字段 ---> Field , 普通方法 ----> Method }
* ==================================================================
*
* spring 機制 :
* <bean id = " xx " class = " com.xsh.User " ></bean>
* ====> 通過 Class.forName( " 類的全路徑 ") 擷取 位元組碼檔案
* 以位元組碼檔案為紐帶,建立執行個體.
*
---------------------------------------------------------
@Test
public void ReflectionTest2() throws Exception {
// 1/擷取位元組碼檔案
Class userClass = Class.forName("User");
//2/需要建立一個對象, ===> 建立對象一定需要調用構造方法 調用類中的無參構造方法來建立構造對象
Constructor[] constructors = userClass.getConstructors();
for (Constructor constructor : constructors ) { ====>
System.out.println(constructor); ====> for循環列印是以構造方法
} ====>
//通過位元組碼擷取無參構造方法
Constructor constructor =userClass.getConstructor();
//通過無參構造方法,建立對象
User u = (User) constructor.newInstance();
System.out.println(u); ===> 列印出對象: 證明通過映射成功建立對象
//通過位元組碼擷取有參構造方法
Constructor constructor1 = userClass.getConstructor(String.class,int.class);
User uu = (User) constructor1.newInstance("張三",21); ===> 這裡是指派給通過映射建立的對象
System.out.println(uu); ===> 列印出對象: 證明通過映射成功建立對象
}
------------------------------------------------------------
反射對象和傳統對象效率相比: 反射的效率比傳統方式低很多
----> 建立一百個對象速度相比,低至 10~ 20 倍 我自己測是這樣的 , 總結就是低很多...量越大,效率越低
------------------------------------------------------------
==================================================================================================================
public class User {
private String name = "張三李四"; //姓名
int age = 26; //年齡
protected float weight = 60.5F; //體重
public float height = 180.5F; //身高
構造方法略過....
}
==================================================================================================================
1 / 在不給出任何接口的情況下( toString 方法也不給出 )如何擷取到User類中私有屬性的值 ? ====> 反射
-------------------------------------------------------------------------
* ==================================================================
* 通過反射擷取某一個實體對象的屬性字段及其值
* 1/通過反射擷取public.protect,預設修飾符修飾的屬性字段和值
* 2/通過暴力反射擷取 私有屬性字段及其值 private 修飾的
* ==================================================================
* 反射裡将屬性封裝成了field類型 :
* 修飾符 資料類型 屬性名
* getFields() ===> 隻能擷取public修飾的屬性
* getDeclaredFields ====> 擷取除了私有的之外的三種修飾符修飾的字段 jdk 8 擷取全部
=================================================================
@Test
public void test() throws Exception {
//建立一個對象
Class c = User.class;
User user = (User) c.getConstructor().newInstance();
//擷取user這個對象的屬性字段
Field[] fields = c.getDeclaredFields();
for (Field s : fields ) { [ 這裡僅僅是部分方法 僅供參考 ]
System.out.println(s);
}
//擷取指定字段的屬性 [ 預設=> 0 public=>1 protected =>4 private =>2 ]
Field field = c.getDeclaredField("weight");
System.out.println(field.getType()); //擷取字段類型
System.out.println(field.getModifiers()); //傳回修飾符的值
System.out.println(field.getName()); //擷取字段名字
System.out.println(field.getDeclaringClass().getTypeName()); //擷取屬性類路徑
}
=================================================================
@Test
public void test() throws Exception {
//建立一個對象
Class c = User.class;
User user = (User) c.getConstructor().newInstance();
//擷取user這個對象的屬性字段
Field[] fields = c.getDeclaredFields();
for (Field s : fields ) {
// System.out.println(s);
}
//擷取指定字段的屬性
Field field = c.getDeclaredField("name");
System.out.println(field.getType()); //擷取字段類型
System.out.println(field.getModifiers()); //傳回修飾符的值
System.out.println(field.getName()); //擷取字段名字
System.out.println(field.getDeclaringClass().getTypeName()); //擷取屬性類路徑
//暴力反射 ==> 擷取所有屬性的值 如果某個屬性被私有化,想要擷取就需要通過暴力反射
field.setAccessible(true);
Object o = field.get(user);
System.out.println(o);
//修改某字段值
field.set(user,"牛二劉三");
System.out.println(user); //修改成功
}
=================================================================
========================================================================================================================
[ 預設=> 0 public=>1 protected =>4 private =>2 ] 為什麼沒有3?
1Byte = 8 bit
位元組 位 計算機底層 二進制 一個位元組 ==> 8 位
計算機傳輸的時候每次最少是一個八位的位元組
1==> 高電壓
0==> 低電壓 00000000 0
00000010 1*2^0 = 1
00000100 1*2^1 = 2
00001000 1*2^2 = 4
這樣的傳輸效率最高 === > 是以沒有 3 !
========================================================================================================================