国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 關于Java中反射機制的深入講解

關于Java中反射機制的深入講解

2021-05-26 13:31像風一樣i Java教程

反射(Reflection)是Java 程序開發語言的特征之一,它允許運行中的 Java 程序獲取自身的信息,并且可以操作類或對象的內部屬性,下面這篇文章主要給大家介紹了關于Java中反射機制的相關資料,需要的朋友可以參考下

前言

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

一:class類

在面向對象的世界里,萬物皆對象。類也是對象,類是java.lang.class類的實例對象。

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

基本的 java 類型(boolean、byte、char、short、int、long、float 和 double)和關鍵字 void 也表示為 class 對象。

class 沒有公共構造方法。class 對象是在加載類時由 java 虛擬機以及通過調用類加載器中的 defineclass 方法自動構造的。

上面來自于jdk的羅里吧嗦,下面我來說下自己的體會:

類不是抽象的,類是具體的!

類是.class字節碼文件,要想獲取一個class實例對象,首先需要獲取.class字節碼文件!

然后調用class對象的一些方法,進行動態獲取信息以及動態調用對象方法!

二:類類型

新建一個foo類。foo這個類也是實例對象,是class的實例對象。

不知道你是否在意過類的聲明與方法的聲明:

?
1
2
3
4
5
6
7
8
public class foo{
 foo(){
  //構造方法
 }
}
public foo method(){
 //...
}

我們知道public后跟返回類型,也就可以知道class也是一個類型。

如何表示class的實例對象?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void main(string[] args) {
//foo的實例對象,new 就出來了
foo foo1 = new foo();
 
//如何表示?
//第一種:告訴我們任何一個類都有一個隱含的靜態成員變量class
class c1 = foo.class;
 
//第二種:已經知道該類的對象通過getclass方法
class c2 = foo1.getclass();
system.out.println(c1 == c2);
 
//第三種:動態加載
class c3 = null;
try {
 c3 = class.forname("cn.zyzpp.reflect.foo");
} catch (classnotfoundexception e) {
 e.printstacktrace();
}
 
system.out.println(c2 == c3);
}

上述打印結果全是true

盡管 c1或c2 都代表了foo的類類型,一個類只能是class類的一個實例變量。

我們完全可以通過類的類類型(class類型)創建類的實例對象。

?
1
2
3
4
5
6
7
8
9
10
//此時c1 c2 c3為class的實例對象
 try {
//  foo foo = (foo)c1.newinstance();
  foo foo = (foo)c3.newinstance();
  foo.print();
 } catch (instantiationexception e) {
  e.printstacktrace();
 } catch (illegalaccessexception e) {
  e.printstacktrace();
 }

靜態加載

new 創建對象是靜態加載類,在編譯時刻就需要加載所有的可能使用到的類 。

動態加載

使用 class.forname("類的全稱") 加載類稱作為動態加載 。

編譯時刻加載類是靜態加載類,運行時刻加載類是動態加載類。

舉個例子

定義office類

?
1
2
3
4
5
public class office {
 public void print() {
 system.out.println("office");
 }
}

定義loading類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class loading {
 
 public static void main(string[] args) {
 try {
  //在運行時再動態加載類
  //arg[0] 為java執行命令時傳的參數
  class<?> a = class.forname(args[0]);
  office office = (office) a.newinstance();
  office.print();
 } catch (classnotfoundexception e) {
  e.printstacktrace();
 } catch (illegalaccessexception e) {
  e.printstacktrace();
 } catch (instantiationexception e) {
  e.printstacktrace();
 }
 }
}

執行過程

d:\>javac -encoding utf-8 loading.java office.java

d:\>java loading office
office

通過class a=class.forname(arg[0])動態加載獲取類,因編譯時不知道使用哪個類,因此編譯沒有加載任何類,直接通過編譯,運行時,根據 java loading office (office是一個類類型/類,下標arg[0]),去確定a是哪個類。這就是動態加載。如果office類不存在,此時運行會報錯。這就是為何有時候會出現編譯通過,運行報錯的原因。

動態加載一個好處,就是可以隨時增加需要編譯的類。例如把office改造為抽象類或接口,定義不同的子類,動態選擇加載。

三:類的反射

通過上面的三種方法獲取到類的類類型,就可以獲取到該類的成員方法,成員變量,方法參數注釋等信息。

方法對象是method類,一個成員方法就是一個method對象。

 

方法 解釋
getmethods() 返回該類繼承以及自身聲明的所有public的方法數組
getdeclaredmethods() 返回該類自身聲明的所有public的方法數組,不包括繼承而來

 

成員變量也是對象,是java.lang.reflect.field對象,field類封裝了關于成員變量的操作。

 

方法 解釋
getfields() 獲取所有的public的成員變量信息,包括繼承的。
getdeclaredfields() 獲取該類自己聲明的成員變量信息,public,private等

 

獲取java語言修飾符(public、private、final、static)的int返回值,再調用modifier.tostring()獲取修飾符的字符串形式,注意該方法會返回所有修飾符。

 

方法 解釋
getmodifiers() 以整數形式返回由此對象表示的字段的 java 語言修飾符。

 

獲取注釋

 

方法 解釋
getannotations() 返回此元素上存在的所有注釋。
getdeclaredannotations() 返回直接存在于此元素上的所有注釋。

 

構造函數也是對象,是java.lang.reflect.constructor的對象。

 

方法 解釋
getconstructors() 返回所有public構造方法
getdeclaredconstructors() 返回類的所有構造方法,不止public

 

完整示例

?
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
private void printclassmessage(object obj){
//要獲取類的信息,首先獲取類的類類型
class clazz = obj.getclass();
//獲取類的名稱
system.out.println(modifier.tostring(clazz.getmodifiers())+" "+ clazz.getclass().getname()+" "+clazz.getname()+"{");
 
system.out.println("----構造方法----");
 
//構造方法
constructor[] constructors = clazz.getdeclaredconstructors();
for (constructor constructor: constructors){
 //構造方法修飾符與名字
 system.out.print(modifier.tostring(constructor.getmodifiers())+" "+constructor.getname()+"(");
 //構造函數的所有參數類型
 class[] parametertypes = constructor.getparametertypes();
 for (class c: parametertypes){
 system.out.print(c.getname()+", ");
 }
 system.out.println("){}");
}
 
system.out.println("----成員變量----");
 
//成員變量
field[] fields = clazz.getdeclaredfields();
for (field field: fields){
 system.out.println(" "+modifier.tostring(field.getmodifiers())+" "+field.gettype().getname() + " " + field.getname()+";");
}
 
system.out.println("----成員方法----");
 
//method類,方法對象,一個成員方法就是一個method對象
method[] methods = clazz.getdeclaredmethods();
for (method method : methods){
 //獲取方法返回類型
 class returntype = method.getreturntype();
 //獲取方法上的所有注釋
 annotation[] annotations = method.getannotations();
 for (annotation annotation: annotations){
 //打印注釋類型
 system.out.println(" @"+annotation.annotationtype().getname()+" ");
 }
 //打印方法聲明
 system.out.print(" "+modifier.tostring(returntype.getmodifiers())+" "+returntype.getname()+" "+method.getname()+"(");
 //獲取方法的所有參數類型
 class<?>[] parametertypes = method.getparametertypes();
 //獲取方法的所有參數
 parameter[] parameters = method.getparameters();
 for (parameter parameter: parameters){
 //參數的類型,形參(全是arg123..)
 system.out.print(parameter.gettype().getname()+" "+parameter.getname()+", ");
 }
 system.out.println(")");
}
system.out.println("}");
}

以string對象為例,打印結果:

public final java.lang.class java.lang.string{
----構造方法----
public java.lang.string([b, int, int, ){}
 java.lang.string([c, boolean, ){}
----成員變量----
 private final [c value;
 private int hash;
----成員方法----
 @java.lang.deprecated
 public abstract final void getbytes(int arg0, int arg1, [b arg2, int arg3, )
 ......
}

四:方法的反射

定義了一個類foo用于測試

?
1
2
3
4
5
public class foo{
 public void print(string name,int num) {
 system.out.println("i am "+name+" age "+num);
 }
}

目標:通過反射獲取該方法,傳入參數,執行該方法!

1.獲取類的方法就是獲取類的信息,獲取類的信息首先要獲取類的類類型

?
1
class clazz = foo.class;

2.通過名稱+參數類型獲取方法對象

?
1
method method = clazz.getmethod("print", new class[]{string.class,int.class});

3.方法的反射操作是通過方法對象來調用該方法,達到和new foo().print()一樣的效果

方法若無返回值則返回null

?
1
object o = method.invoke(new foo(),new object[]{"name",20});

五:通過反射認識泛型

?
1
2
3
4
5
6
7
8
9
10
11
public static void main(string[] args) {
 arraylist<string> stringarraylist = new arraylist<>();
 stringarraylist.add("hello");
 arraylist arraylist = new arraylist();
 
 class c1 = stringarraylist.getclass();
 class c2 = arraylist.getclass();
 
 system.out.println(c1 == c2);
 
}

打印結果為true

c1==c2的結果返回說明編譯之后集合的泛型是去泛型化的。換句話說,泛型不同,對類型沒有影響。

java中集合的泛型其實只是為了防止錯誤輸入,只在編譯階段有效,繞過編譯就無效。

驗證

我們可以通過反射來操作,繞過編譯。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(string[] args) {
 arraylist<string> stringarraylist = new arraylist<>();
 stringarraylist.add("hello");
 arraylist arraylist = new arraylist();
 class c1 = stringarraylist.getclass();
 class c2 = arraylist.getclass();
 system.out.println(c1 == c2);
 
 try {
  method method = c1.getmethod("add",object.class);
  method.invoke(stringarraylist,20);
  system.out.println(stringarraylist.tostring());
 } catch (nosuchmethodexception e) {
  e.printstacktrace();
 } catch (illegalaccessexception e) {
  e.printstacktrace();
 } catch (invocationtargetexception e) {
  e.printstacktrace();
 }
 
}

打印結果:

true
[hello, 20]

成功繞過了泛型<string>的約束。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:https://www.cnblogs.com/yueshutong/p/9495001.html

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 亚洲自拍另类 | 亚洲精品久久久久久动漫 | 中文字幕亚洲精品 | 久久亚洲综合 | 色综合视频在线 | 国产精品视频久久 | 综合九九| 国产精品欧美一区二区三区 | 久久精品国产一区二区三区不卡 | 亚洲免费中文字幕 | 91麻豆精品国产91久久久更新时间 | 亚洲专区 中文字幕 | 在线播放一区二区三区 | 亚洲一区av在线 | 99久久婷婷| 日韩免费 | 亚洲www啪成人一区二区 | 亚洲www视频 | 久久人人爽爽爽人久久久 | 一级毛片免费 | 久久精品无码一区二区日韩av | 男人天堂a | 午夜国产视频 | 亚洲视频一区在线 | 91精品国产高清一区二区三区 | 国产精品美女www爽爽爽软件 | 韩国av一区二区 | 91精品欧美久久久久久动漫 | av最新在线 | 久久中文字幕一区二区三区 | 亚洲精品一区二三区不卡 | 亚洲一区国产视频 | 中文在线视频 | 日韩成人在线视频 | 91视频8mav | 在线精品一区 | 久久久青草婷婷精品综合日韩 | 中文字幕2019 | 亚洲自拍偷拍一区 | 欧美激情在线播放 | 欧美日韩一区二 |