生活随笔
收集整理的這篇文章主要介紹了
JAVA_反射机制(照镜子)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
反射
首先反射,當你照鏡子的時候你的面部的個個部位都會通過鏡子反射出來,讓你看道你自己。而JAVA也會像我們一樣,也有一面鏡子,它可以通過這面鏡子,看到自己的一些信息。JAVA反射機制就是對于一段程序,在運行的時候才知道要準備操作的類是什么,并可以在運行的時候獲取類的完整構造,并調用對應的方法,獲取.class文件。而我們就可以通過java反射機制得到一些程序中的類的一些具體信息,參數,方法等。JAVA反射機制用在并不知道初始化的類對象是什么,然而我們無法使用new關鍵字來創建一個對象對它的方法屬性進行調用。這時我們就利用JAVA反射機制,動態獲取對象的信息,和調用方法 ,這一功能就是反射機制。
Class
對于java反射機制的原理就是在Class類中,首先簡單講解一下class類這里并不會主要解釋,主要是涉及一些方法去使用。首先官方解釋為,**Class 類的實例表示正在運行的 Java 應用程序中的類和接口。枚舉是一種類,注釋是一種接口。每個數組屬于被映射為 Class 對象的一個類,所有具有相同元素類型和維數的數組都共享該 Class 對象。基本的 Java 類型(boolean、byte、char、short、int、long、float 和 double)和關鍵字 void 也表示為 Class 對象。**也就是說Class類保存這些類型信息的類。當加載一個.class文件時,就創建這個類的class對象,之后的對象都是由這個class對象創建的,所以對于同一個類的所有對象,class對象只有一個。
A a
= new A ( ) ; A b
= new A ( ) ; a
. class = b
. class ;
Class無公共構造方法,Class 對象是在加載類時由 Java 虛擬機以及通過調用類加載器中的 defineClass 方法自動構造的。而對于反射機制來說,就是將java類中的各種成分映射成一個個java類的對象,對于一個類的方法,構造方法,變量等,這些成員在加入類中都會有一個Class類來描述。 接下來主要簡單講解一下我們通過正常new()的方式去創建一個對象是如何實現的。 首先我們一個類中的構造方法,變量,方法等相關信息都是在class類中,當我們對類A 去new() 一個對象a 時 JVM 會去加載A.class,將會在磁盤找到A.class文件,并加載到JVM內存中,這時我們創建的A類的對象空間就會去指向A類中的相關信息,而A類的信息都是由class對象指向的,所以也可這樣說A類的對象可以有多個,但是class的對象只有一個。 接下來就將簡單介紹幾個Class類的方法。
1. static Class
< ? > forName ( String className
)
2. String
getName ( )
3. T
newInstance ( )
并不是Class類的方法只有這幾個,而是對于反射機制,我們會用到這幾個方法,但是進入反射實戰之前,我們先簡單說一下 newInstance() ; 該方法可以創建class對象所表示的類的新實例,而他和我們去new()一個方法有什么區別呢?? 首先 newInstance() :弱類型,低效率,只能調用無參的構造方法。 new():強類型,相對高效,能調用任何public構造。 下面我還是通過一段代碼看看 newInstance()具體如何實現的。
package java_反射機制之
class 類創建一個實例
;
import java
. util
. concurrent
. Callable
;
import java
. lang
. Class
;
import static java
. lang
. Class
. forName
;
public class test { public static void main ( String
[ ] args
) throws Exception
{ Class
c = Class
. forName ( "java_反射機制之class類創建一個實例.test2" ) ; test2 t
= ( test2
) c
. newInstance ( ) ; t
. show ( ) ; }
}
interface test1 { abstract void show ( ) ;
}
class test2 implements test1 { @Override public void show ( ) { System
. out
. println ( "使用接口" ) ; }
}
運行結果:使用接口
這里去使用 newInstance()去創建test2()類的一個實例,然后通過該實例去調用接口中的方法。然后對于newInstance()所返回的類型是Object類型,所以我們要其進行強制轉型。
反射實戰
首先對于反射我們先要
獲取反射的class對象 2.通過反射創建類對象 3.通過反射獲取類屬性及構造器 首先對于第一部最重要就是我們如何獲取反射的class類的對象。這里我們比較常用的就是 **Class.forName(String className) ** 接下來我們先用反射去獲取不同修飾類型的構造方法,在這之前先了解一下相關方法:
package java_反射機制獲取構造方法
;
import java
. lang
. Class
;
import java
. lang
. reflect
. Constructor
; public class test { test ( String str
) { System
. out
. println ( "默認的構造方法" + str
) ; } public test ( ) { System
. out
. println ( "調用共有無參構造方法并執行" ) ; } public test ( int age
) { System
. out
. println ( "調用共有有參構造方法 " + age
) ; } private test ( char name
) { System
. out
. println ( "調用私有有參構造方法" + name
) ; } protected test ( boolean n
) { System
. out
. println ( "調用受保護的構造方法 " + n
) ; } public static void main ( String
[ ] args
) throws Exception
{ Class
c = Class
. forName ( "java_反射機制獲取構造方法.test" ) ; System
. out
. println ( "****所有共有構造方法******" ) ; Constructor
[ ] con
= c
. getConstructors ( ) ; for ( Constructor i
: con
) { System
. out
. println ( i
) ; } System
. out
. println ( "*****獲取單個共有構造方法并調用******" ) ; Constructor cn
= c
. getConstructor ( int . class ) ; System
. out
. println ( cn
) ; cn
. newInstance ( 10 ) ; System
. out
. println ( "*****獲取某個受保護的構造方法并調用" ) ; Constructor cn1
= c
. getDeclaredConstructor ( boolean . class ) ; System
. out
. println ( cn1
) ; cn1
. newInstance ( true ) ; }
}
class test2 { public static void main ( String
[ ] args
) throws Exception
{ Class
c = Class
. forName ( "java_反射機制獲取構造方法.test" ) ; System
. out
. println ( "***單個獲取私有構造方法并調用*****" ) ; Constructor cn
= c
. getDeclaredConstructor ( char . class ) ; cn
. setAccessible ( true ) ; cn
. newInstance ( 'a' ) ; }
}
運行結果:
* * * * 所有共有構造方法
* * * * * *
public java_反射機制獲取構造方法
. test ( int )
public java_反射機制獲取構造方法
. test ( )
* * * * * 獲取單個共有構造方法并調用
* * * * * *
public java_反射機制獲取構造方法
. test ( int )
調用共有有參構造方法
10
* * * * * 獲取某個受保護的構造方法并調用
protected java_反射機制獲取構造方法
. test ( boolean )
調用受保護的構造方法
true
test2運行結果:
* * * 單個獲取私有構造方法并調用
* * * * *
調用私有有參構造方法a
這里主要簡單講解一下關于如何獲取構造方法,并去調用。這里能我創建了兩個類,在不同的類下去反射獲取構造方法并去調用,我們先來簡單講解一下在test 類下的調用方法: 首先就是先獲取class類的對象,然后通過調用獲取單個構造方法的方法去獲取構造方法,之后去調用構造方法,這是簡單的流程。 對于test2 類中對于去調用私有構造方法時,使用到了**setAccessible()**暴力訪問,強制忽略私有修飾符。 接下來我們對于反射獲取方法并調用的代碼演示 先讓我們看一下使用到相關方法:
package java_反射機制獲取成員方法
;
import java
. lang
. reflect
. Method
;
public class test { public void show ( String s
) { System
. out
. println ( "獲取有參公開方法" + s
) ; } public void show1 ( ) { System
. out
. println ( "獲取無參公開方法" ) ; } private void show2 ( int i
) { System
. out
. println ( "獲取私有構造方法" + i
) ; } public static void main ( String
[ ] args
) throws Exception
{ Class
c = Class
. forName ( "java_反射機制獲取成員方法.test" ) ; System
. out
. println ( "或許所有公開方法" ) ; Method
[ ] m
= c
. getMethods ( ) ; for ( Method i
: m
) { System
. out
. println ( i
) ; } System
. out
. println ( "獲取公開方法并調用" ) ; Method m1
= c
. getMethod ( "show" , String
. class ) ; test t
= ( test
) c
. newInstance ( ) ; m1
. invoke ( t
, "***" ) ; }
}
class test1 { public static void main ( String
[ ] args
) throws Exception
{ Class
c = Class
. forName ( "java_反射機制獲取成員方法.test" ) ; System
. out
. println ( "異類獲取并調用私有方法" ) ; Method m
= c
. getDeclaredMethod ( "show" , String
. class ) ; test t
= ( test
) c
. newInstance ( ) ; m
. setAccessible ( true ) ; m
. invoke ( t
, "這里是異類" ) ; }
}
運行結果:
public static void java_反射機制獲取成員方法
. test
. main ( java
. lang
. String
[ ] ) throws java
. lang
. Exception
public void java_反射機制獲取成員方法
. test
. show ( java
. lang
. String
)
public void java_反射機制獲取成員方法
. test
. show1 ( )
public final native void java
. lang
. Object
. wait ( long ) throws java
. lang
. InterruptedException
public final void java
. lang
. Object
. wait ( long , int ) throws java
. lang
. InterruptedException
public final void java
. lang
. Object
. wait ( ) throws java
. lang
. InterruptedException
public boolean java
. lang
. Object
. equals ( java
. lang
. Object
)
public java
. lang
. String java
. lang
. Object
. toString ( )
public native int java
. lang
. Object
. hashCode ( )
public final native java
. lang
. Class
java. lang. Object. getClass ( )
public final native void java
. lang
. Object
. notify ( )
public final native void java
. lang
. Object
. notifyAll ( )
獲取公開方法并調用
獲取有參公開方法
* * *
從運行結果也不難看出,我們獲取的方法包含了父類的方法,也包括了Object類的方法。就主要簡單講解一下如何調用方法的,首先也是獲取單個你需要的方法,之后這里就使用到了剛剛通過 newInstance() 去創建一個新的實列,然后通過該實例去對獲取的方法調用,并賦值。而對于異類中對于獲取到的私有方法的調用也是用到了**setAccessible()**去暴力訪問。 接下來就是關于成員變量的獲取和調用 先看一下相關方法:
package java_反射機制獲取成員變量
;
import java
. lang
. reflect
. Field
;
public class test { public String name
; protected int age
; private String phone
; public String
getPhone ( ) { return phone
; } public void setPhone ( String phone
) { this . phone
= phone
; } @Override public String
toString ( ) { return "test{" + "name='" + name
+ '\'' + ", age=" + age
+ ", phone='" + phone
+ '\'' + '}' ; } public static void main ( String
[ ] args
) throws Exception
{ Class
c = Class
. forName ( "java_反射機制獲取成員變量.test" ) ; System
. out
. println ( "*****獲取共有字段*****" ) ; Field
[ ] fi
= c
. getFields ( ) ; for ( Field i
: fi
) { System
. out
. println ( i
) ; } System
. out
. println ( "*****單個獲取共有字段并賦值*******" ) ; Field fi1
= c
. getField ( "name" ) ; System
. out
. println ( fi1
) ; test t
= ( test
) c
. newInstance ( ) ; fi1
. set ( t
, "***" ) ; System
. out
. println ( t
. name
) ; }
}
class test2 { public static void main ( String
[ ] args
) throws Exception
{ Class
c = Class
. forName ( "java_反射機制獲取成員變量.test" ) ; System
. out
. println ( "*****不同類下獲取私有字段并賦值******" ) ; Field fi
= c
. getDeclaredField ( "phone" ) ; System
. out
. println ( fi
) ; test t2
= ( test
) c
. newInstance ( ) ; fi
. setAccessible ( true ) ; fi
. set ( t2
, "**" ) ; System
. out
. println ( t2
. getPhone ( ) ) ; }
}
運行結果:
* * * * * 獲取共有字段
* * * * *
public java
. lang
. String java_反射機制獲取成員變量
. test
. name
* * * * * 單個獲取共有字段并賦值
* * * * * * *
public java
. lang
. String java_反射機制獲取成員變量
. test
. name
* * *
這里同理也是使用到了 newInstance()去創建一個新的實例,然后對于獲取到的變量進行賦值操作,對于異類中,對于私有變量的調用,也是使用到了setAccessible()進行暴力訪問。 接下來我個人覺得較為有用的就是關于反射機制越過泛型 直接看例子
package java_反射機制越過泛型
; import java
. lang
. reflect
. Method
;
import java
. util
. ArrayList
;
import java
. util
. List
;
import java
. util
. concurrent
. Callable
; public class test { public static void main ( String
[ ] args
) throws Exception
{ ArrayList
< String> l
= new ArrayList < > ( ) ; l
. add ( "a" ) ; l
. add ( "b" ) ; Class
c = l
. getClass ( ) ; Method m
= c
. getMethod ( "add" , Object
. class ) ; m
. invoke ( l
, 10 ) ; for ( Object i
: l
) { System
. out
. println ( i
) ; } }
}
運行結果:
a
b
10
程序只要就是起先定義一個String類型的集合,但此時我想要往集合內存Integer類型的變量,這里我就將通過反射機制獲取ArrayList下的add()方法,然后進行賦值,之后再對集合進行遍歷。這里我們使用到getClass()方法去獲取Class類的對象,因為之前已經創建好了ArrayList的一個對象。 好了到這為止對于java反射機制的相關使用簡單的整理了一下,唯一還有就是通過反射機制獲取main下的方法這里就通過一段代碼展示,與上面的原理相同
package java_反射機制反射mian的方法
; import java
. lang
. reflect
. Method
; public class test { public static void main ( String
[ ] args
) { System
. out
. println ( "這里是main函數的方法" ) ; for ( int i
= 0 ; i
< args
. length
; i
++ ) { System
. out
. println ( args
[ i
] ) ; } }
}
class test1 { public static void main ( String
[ ] args
) throws Exception
{ Class
c = Class
. forName ( "java_反射機制反射mian的方法.test" ) ; Method m
= c
. getMethod ( "main" , String
[ ] . class ) ; m
. invoke ( null
, ( Object
) new String [ ] { "a,b,c" } ) ; }
}
總結
以上是生活随笔 為你收集整理的JAVA_反射机制(照镜子) 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。