學(xué)習(xí)筆記20170601">【PMP】學(xué)習(xí)筆記20170601
813
2022-05-30
文章目錄
注解
內(nèi)置注解
元注解
自定義元注解
反射
獲取反射對象
Class類型
獲取Class類
擁有Class對象
類加載內(nèi)存分析
類初始化
類的主動引用(一定發(fā)生類的初始化)
類的被動引用(不會發(fā)生類的初始化)
類加載器
獲取運行時類的對象
動態(tài)創(chuàng)建對象執(zhí)行方法
通過構(gòu)造器創(chuàng)建對象(實例化對象):
通過反射獲取一個方法
通過反射操作屬性
通過反射操作泛型
通過反射操作注解
獲取注解的value的值
獲取類指定的注解
注解
java.Annotation
對程序作出解釋,可以被其他程序讀取,有檢測的作用
格式:@注釋名,也可以添加一些參數(shù)值
@Override : java.lang.Override ,只修辭方法,表面一個方法打算重寫超類的另一個方法聲明
@Depercated : java.lang.Depercated ,修辭方法,屬性,類。表示不鼓勵程序員使用這樣的元素。使用時會加杠。
@SuppressWarnings: java.lang.SuppressWarnings,用來抑制編譯時產(chǎn)生的警告信息(出現(xiàn)警告信息),需要添加參數(shù)。@SuppressWarnings(“all”),@SuppressWarnings(“unchecked”)
元注解作用是負(fù)責(zé)注解其他注解,java定義了4個標(biāo)準(zhǔn)的meta-annotation類型
@Target:注解使用范圍
@Retention:在什么級別保存該注釋信息,用于描述注解的聲明周期(SOURCE(源碼) < CLASS < RUNTIME)
@Documented:是否生成文檔注釋javadoc
@Inherited:聲明子類可以繼承父類中的該注解
@Target(value = ElementType.METHOD) // 只能定義于方法上,可以查看ElementType源碼,填寫自己想定義的范圍
@Target(value = { ElementType.METHOD, ElementType.TYPE }) // 可以放在類和方法上面,可以查看ElementType源碼,填寫自己想定義的范圍
@Retention(value = RetentionPolicy.RUNTIME) //表示運行時有效
@Documented //注解是否生成在Javadoc中
@Inherited //子類可以繼承父類中的注解
public @interface MyAnnotation{
}
@interface:自動繼承java.lang.annotation.Annotation接口
其中的每一個方法實際上是聲明了一個配置參數(shù)
方法的名稱就是參數(shù)的名稱
返回值類型就參數(shù)的類型(返回值類型只能是基本類型:Class,String,enum)
可以使用default來聲明參數(shù)的默認(rèn)值
如果只有一個參數(shù)成員,一般名為value
注解元素必須要有值,定義時通常使用空字符串,0作為默認(rèn)值
一般寫法:
@Target(value = { ElementType.TYPE, ElementType.METHOD}) @Retention(value = RetentionPolicy.RUNTIME) public @interface MyAnnotation{ //注解的參數(shù):參數(shù)類型+參數(shù)名(); String name() default ""; int age() default 0; int id() default -1; //默認(rèn)值為-1,則代表不存在 String[] schools() default { "XXX", "X"}; } //使用自定義注解: @MyAnnotation(name = "XXX") //注解元素必須要有值,如果使用default "" ,則可以不寫name:@MyAnnotation() //注解的參數(shù)沒有順序 public void test() { } @Target(value = { ElementType.TYPE, ElementType.METHOD}) @Retention(value = RetentionPolicy.RUNTIME) public @interface MyAnnotation1{ String value();//一個參數(shù),默認(rèn)用value } @MyAnnotation1("XXX") //使用value作為注解參數(shù),使用時可以省略value參數(shù) public void test() { }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
反射
java.Reflection
反射是java被視為準(zhǔn)動態(tài)語言的關(guān)鍵,反射機制運行程序在執(zhí)行期間借助Reflection API 取得任何類的內(nèi)部消息(類名,接口,方法等等),并能直接操作任意對象的內(nèi)部屬性及方法。
Class c = Class.forName(“java.lang.String”)
加載完類,在堆內(nèi)存的方法區(qū)中有一個Class類型的對象(一個類只有一個Class對象),這個對象就包含了完整的類的結(jié)構(gòu)信息。我們可以通過這個對象看到類的結(jié)構(gòu)
方式:實例化對象–>getClass()方法–>得到完整的"包類"名稱
java.lang.Class:代表一個類
java.lang.reflect.Method:代表類的方法
java.lang.reflect.Field:代表類的成員變量
java.lang.reflect.Constructor:代表類的構(gòu)造器
方法:定義一個實體類( pojo,entity )User
Class c = Class.forName(“包名.User”);
//一個類只有一個Class對象,一個類加載后,類的整個結(jié)構(gòu)都會被封裝在Class對象中
c.方法();
Object類中的getClass() 方法將返回一個Class類,getClass() 方法可以被所有類繼承。
Class本身也是一個類
Class對象只能由系統(tǒng)建立對象
一個加載的類在JVM中只有一個Class實例
一個Class對象對應(yīng)的是一個加載到JVM中的一個.class文件
每一個類的實例都會記得生成自己的Class實例
Class類是Refection的根源,要動態(tài)加載,運行的類,要先獲取相應(yīng)的Class對象
已知具體的類,使用類名:Class c = Person.class;
已知類的實例:Class c = person.getClass();
已知類的全類名,且該類在類路徑下:Class c = Class.forName(“demo.Student”);
內(nèi)置基本數(shù)據(jù)類型(包裝類):使用類名.Type
class:外部類,成員(成員內(nèi)部類,靜態(tài)內(nèi)部類),局部內(nèi)部類,匿名內(nèi)部類
interface,數(shù)組,enum,annotation,基本數(shù)據(jù)類型,void
注意:只有元素類型和維度,就是同一個class
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-sgIgXXfc-1617933654538)(C:\Users\FYC\AppData\Roaming\Typora\typora-user-images\image-20210401161527681.png)]
加載到內(nèi)存,產(chǎn)生一個類對應(yīng)的class對象(堆中)
鏈接(棧)
初始化(){ 合并static修飾的方法,成員變量等等 }
初始化main方法所在的類
new一個類的對象
調(diào)用類的靜態(tài)成員(除final常量)和靜態(tài)方法
對類進(jìn)行反射調(diào)用
初始化類,父類沒有初始化,則先初始化父類
訪問一個靜態(tài)域時,只有當(dāng)聲明這個域的類才會被初始化。例如:子類調(diào)用父類的靜態(tài)變量,不會導(dǎo)致子類初始化。
通過數(shù)組定義類引用。只是一個名字和空間
引用常量final不會觸發(fā)(常量在鏈接階段就存入調(diào)用類的常量池中了)。
程序是使用類加載器一步步加載的
將class文件字節(jié)碼內(nèi)容加載到內(nèi)存中,將這些靜態(tài)數(shù)據(jù)轉(zhuǎn)換為方法區(qū)的運行是數(shù)據(jù)結(jié)構(gòu),在堆中生成一個代表這個類的java.lang.Class對象,作為方法區(qū)中的類數(shù)據(jù)的訪問入口
在類加載時創(chuàng)建一個Class對象
類緩存:類加載到類加載器中,這個類將緩存一段時間,JVM垃圾回收機制(gc)可以回收這些Class對象。
引導(dǎo)類加載器:負(fù)責(zé)Java平臺核心庫(rt.jar),裝載核心類庫,無法直接獲取
擴展類加載器:ext文件夾下的jar
系統(tǒng)類加載器
//獲取系統(tǒng)類加載器 ClassLoader sys = ClassLoader.getSystemClassLoader(); //獲取系統(tǒng)類加載器的父類加載器:擴展類加載器 ClassLoader parent = sys.getParent(); //獲取擴展類加載器的父類加載器:引導(dǎo)類加載器(根加載器(C/C++)) ClassLoader parent = parent.getParent(); //測試當(dāng)前類是哪個加載器加載 ClassLoader classLoader = Class.forName("java.lang.Object").getClassLoader(); //獲取系統(tǒng)類加載器的路徑 System.getProperty("java.class.path");
1
2
3
4
5
6
7
8
9
10
雙親委派機制:多重檢測保證安全性,自己定義的類在jdk中存在,則自己的類不會用。
getName():獲取包名+類的名字
getSimpleName():獲取類的名字
Field[ ] fields = c.getFields():獲取類的public屬性(成員變量等等)
Field[ ] declaredfields = c.getDeclaredFields():獲取類的全部屬性
c.getDeclaredField(“xxx”):獲取類的指定屬性
Method[ ] methods = c.getMethods():獲取本類及其父類的所有public方法
Method[ ] declaredmethods= c.getDeclaredMethods():獲取本類的全部方法
c.getDeclaredMethod(“方法名”, 參數(shù)類型):獲得指定方法,沒有參數(shù)則為null,類實例String.class,int.class 等
Constructor[ ] constructors = c.getConstructors():獲取public構(gòu)造器
Constructor[ ] declaredconstructors = c.getDeclaredConstructors():獲取全部的構(gòu)造器
Constructor declaredconstructor = c.getDeclaredConstructor( 參數(shù)類型 )獲取指定的構(gòu)造器
創(chuàng)建類的對象:調(diào)用Class對象的newInstance()方法
Class c = Class.forName(“XXX”);
創(chuàng)建的類名稱 xxx = (創(chuàng)建的類名稱)c.newInstance();
類必須有一個無參數(shù)的構(gòu)造方法
類的構(gòu)造器的訪問權(quán)限要足夠
**沒有無參構(gòu)造器時創(chuàng)建對象:**Constructor 構(gòu)建
Constructor declaredconstructor = c.getDeclaredConstructor( 參數(shù)類型 )
創(chuàng)建的類名稱 use = (創(chuàng)建的類名稱)Constructor.newInstance(傳遞參數(shù));
Method declaredmethod= c.getDeclaredMethod(“XXX”, 參數(shù)類型)
//invoke:激活。(對象,“方法的參數(shù)”)
field.setAccessible(true) // 取消安全檢測。invoke可以操作private屬性
declaredmethod.invoke(use, “方法的值” );
Object invoke(Object obj, Object…args)
Object 對應(yīng)原方法的返回值,如果沒有返回值,則返回null;如果原方法為靜態(tài)方法,Object obj可以為空;方法的值沒有則寫null
Field field = c.getDeclaredField(“屬性”);
field.setAccessible(true) // 取消安全檢測。set可以操作private屬性
field.set(use, “屬性”);
setAccessible
Field Method Constructor 都有這個方法,作用是啟動和禁用訪問安全檢測的開關(guān)
關(guān)閉開關(guān)加快反射的效率
Type[ ] genericParameterType = c.getGenericParameterType() //獲取泛型(Generic)參數(shù)化類型
通過反射操作泛型有關(guān)的類型:
ParameterizedType:表示一種參數(shù)化類型,例如Collection
GenericArrayType:表示一種元素類型是參數(shù)化類型或者類型變量的數(shù)組類型
TyVariable:各種類型變量的公共父接口
WildcardType:代表一種通配符>類型表達(dá)式
可以進(jìn)行對提取的泛型參數(shù)(genericParameterType)進(jìn)行再提取,判斷genericParameterType與上述類型是否相等,相等則進(jìn)行強轉(zhuǎn),再輸出對應(yīng)的泛型參數(shù)類型。
強轉(zhuǎn):
Type[] actualTypeArguments = ( (ParameterizedType) genericParameterType ).getActualTypeArguments(); //getActualTypeArguments():獲取真實參數(shù)信息
1
2
Type[ ] genericReturnType = c.getGenericReturnType() //獲取泛型(Generic)返回值類型
ORM:Object relationship Mapping – > 對象關(guān)系映射
Annotation[ ] annotations = c.getAnnotations();
注解名 xx = (注解名) c.getAnnotations( 注解名.class );
value類型 value = 注解名.value();
Field field = c.getDeclaredField(“屬性”);
類的注解名 xx = field.getAnnotations( 類的注解名.class);
value類型 value = 類的注解名.value();
Java 數(shù)據(jù)結(jié)構(gòu)
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。