1. 程式人生 > >Java反射框架(一)——介紹、Class類

Java反射框架(一)——介紹、Class類

目錄

1.介紹

1.介紹

1.1使用反射

反射提供了檢測調節執行在jvm上的應用的執行時行為的能力

反射是非常強力的功能並且可以令應用執行不可能的操作。

反射的常見應用:

  • 反射機制允許應用可以使用外部的使用者自定義的類,即利用它們的完整限定名稱建立擴充套件物件。
  • 反射機制可以用於構建類瀏覽器實現列舉類成員。
  • 型別資訊可以通過反射獲得,一次幫助開發者編寫正確程式碼。
  • 反射可以檢查類的私有成員。
  • 反射可以系統地呼叫定義在類中的可發現的API集合。

1.2反射的缺點

反射框架十分強力,但是不能隨意使用。

如果不適用反射框架就能達成操作,那最好就不要使用反射。

效能開銷

由於反射涉及動態解析型別,一些jvm的優化不會執行。

安全限制

反射框架需要執行時許可權,但有些SecurityManager不會授權。

內部暴露

反射可以執行非反射程式碼的非法功能,例如,方位private域與方法。

這樣破壞了封裝性,將可能產生程式碼行為混亂以及破壞移植性。

反射破壞了抽象性,所以,當平臺升級時,程式碼行為可能發生改變。

2.Class

對每一種型別的物件,JVM都例項化一個java.lang.Class的不可變例項。

Class提供了檢測物件執行時屬性(即物件的成員與方法)的方法。

Class提供了建立新類與物件的能力。

Class類是Reflection框架的進入點。

2.1遍歷類物件

所有反射操作的進入點都是java.lang.Class。

除了ReflectPermission類,其餘java.lang.reflect中的類都不具有public構造器。

可以通過物件、類名稱、型別、存在的Class來獲取Class物件。

Object.getClass()

Class c = "fff".getClass();

note:獲取String物件"fff"的Class物件。

ps:只有繼承Object的物件,才能以這種方式獲取Class。

ps:對介面物件使用getClass,獲取實現類物件。

語法.class

Class c = boolean.class;

note:獲取boolean的Class。

Class c = int[][][].class;

note:獲取多維陣列的Class。

Class.forName()

Class c = Class.forName("examples.Foo");

note:通過完整類名examples.Foo獲取Foo的Class類。

ps:靜態方法Class.forName()通過使用完整類名獲取對應的Class。

如果Class表示的是陣列,陣列型別名稱的內部形式需要在元素型別名稱之前放置一個或多個'['用以表示巢狀陣列的深度。

Class c = Class.forName("[[[[I");

note:等價於int[][][][].class。

原始型別包裝者的TYPE域

wrapper將原始型別包裝為引用型別。

Class c = Double.TYPE;
Class c = Void.TYPE;

note:第一個Class與doubel.class等價,第二個Class與void.class等價。

返回Class物件的方法

可以通過反射框架APIs提供的一些方法返回Class物件。

Class.getSuperclass()

Class c = javax.swing.JButton.class.getSuperclass();

note:獲取javax.swing.JButton的父類的Class。

Class.getClasses()

Class<?>[] c = Character.class.getClasses();

note:獲取Character內定義的所有的類與介面(即public內部類與介面)的Class,包括繼承的內部類與介面。  

Class.getDeclaringClasses()

獲取內部定義的類與介面(不一定是public)的Class,匿名內部類不算,繼承的內部類也不算。

Class.getDeclaringClass()

如果給定Class是內部類或介面,返回定義了它的類的Class物件,如果不是內部類或介面,返回null。

java.lang.reflect.Field.getDeclaringClass():獲取聲明瞭此域的類的Class物件。

java.lang.reflect.Method.getDeclaringClass()

java.lang.reflect.Constructor.getDeclaringClass()

Class.getEnclosingClass()

獲取封閉類的Class物件,可以用於獲取匿名內部類的封閉類。

2.2檢測類修飾符與型別

java.lang.reflect.Modifier包含了所有可能的修飾符的宣告。

Modifier用於解析Class.getModifiers()返回的修飾符集合。

獲取類名稱

c.getCanonicalName();

note:獲取Class物件c表示的類的名稱。

獲取修飾符

Modifier.toString(c.getModifiers());

note:獲取Class物件c表示的類的所有修飾符。

ps:所有介面都會被jvm設定為abstract。

獲取型別引數名

TypeVariable[] tv = c.getTypeParameters();

note:獲取Class物件c表示的類定義的型別引數名。

獲取實現的介面

Type[] intfs = c.getGenericInterfaces();

note:獲取Class物件c表示的類實現的所有介面。

獲取持有的註解

Annotation[] ann = c.getAnnotations();

note:獲取Class物件c表示的類持有的所有註解。

ps:只有java.lang.annnotation.RetentionPolicy設定為RUNTIME的註解才可以被訪問。

獲取父類

Class<?> ancestor = c.getSuperclass();

note:獲取Class物件c表示的類的父類。

ps:原始型別與Object返回null。

ps:陣列返回Object。

2.3發現類成員

獲取包名

Package p = c.getPackage();

獲取構造器

Constructor[] cs = c.getConstructors();

獲取域

Field[] fs = c.getFields();

ps:java.lang.reflect.Field.isEnumConstant()用於判斷域是否為常量。

獲取方法

Method[] ms = c.getMethods();

獲取內部類

Class[] ccs = c.getClasses();

獲取成員

Member[] mes = c.getFields();

note:使用Member代表域。

ps:Member可以代表域、方法、構造器。

ps:Member沒有包含getGenericString()方法,使用時可以將其轉型。