日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

反射-Class

發布時間:2024/4/13 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 反射-Class 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

通過獲取類的信息你可以獲取以下相關的內容:
Class對象
類名
修飾符
包信息
父類
實現的接口
構造器
方法
變量
注解

示例類定義

接口

public interface IEat {void eat(); } public interface IRun {void run(); }

父類

public abstract class Animal implements IRun,IEat {private String name;private String skin;private double weight;private int legs;public String getSkin() {return skin;}public void setSkin(String skin) {this.skin = skin;}public double getWeight() {return weight;}public void setWeight(double weight) {this.weight = weight;}public int getLegs() {return legs;}public void setLegs(int legs) {this.legs = legs;}public String getName() {return name;}@Overridepublic void run() {// TODO Auto-generated method stub}@Overridepublic void eat() {// TODO Auto-generated method stub}public Animal(String name){this.name =name;}public void sleep() {beforeSleep();//sleep}protected void beforeSleep(){} }

子類

public class Dog extends Animal{public Dog(String name) {super(name);// TODO Auto-generated constructor stub}@Overridepublic void run() {// TODO Auto-generated method stub}@Overridepublic void eat() {// TODO Auto-generated method stub}public void bark(){} } public class Horse extends Animal {public Horse(String name) {super(name);// TODO Auto-generated constructor stub}@Overridepublic void run() {// TODO Auto-generated method stub}@Overridepublic void eat() {// TODO Auto-generated method stub}}

獲取類信息

類名

獲取類名有幾種方法

Class<?> clazzHorse = horse.getClass();//getName:study.reflection.HorseSystem.out.println("getName:" + clazzHorse.getName());//getTypeName:study.reflection.HorseSystem.out.println("getTypeName:" + clazzHorse.getTypeName());//getSimpleName:HorseSystem.out.println("getSimpleName:" + clazzHorse.getSimpleName());//getCanonicalName:study.reflection.HorseSystem.out.println("getCanonicalName:" + clazzHorse.getCanonicalName());byte[] a = new byte[10];Class<?> clazzList= a.getClass();//getName:[BSystem.out.println("getName:" + clazzList.getName());//getTypeName:byte[]System.out.println("getTypeName:" + clazzList.getTypeName());// getSimpleName:byte[]System.out.println("getSimpleName:" + clazzList.getSimpleName());// getCanonicalName:byte[]System.out.println("getCanonicalName:" + clazzList.getCanonicalName());

?

getName()

返回該類對象作為字符串表示的實體(類、接口、數組類、基本數據類型或void)的名稱
可以理解為返回的是 虛擬機中Class對象的表示
當我們 動態加載類 的時候,會用到該方法的返回值,如: 使用 Class.forName() 方法
如果是 內部類,則使用 $ 符號進行連接
如果是 數組,則使用 [ 來表示,數組是幾維,[ 就有幾個
其余情況的表示如下

getCanonicalName()

??? 返回Java語言規范定義的底層類的規范名稱
??? 如果是一個本地類或匿名類或其組件的數組類型沒有規范名稱的,則返回null
??? 可以理解為返回的是 正常的包含路徑的類名
??? 該方法的返回值可以在 import語句中使用
??? 能唯一標識一個類,還可以在toString()或日志操作期間使用
?

??? public String getCanonicalName() {
??????? if (isArray()) {
??????????? String canonicalName = getComponentType().getCanonicalName();
??????????? if (canonicalName != null)
??????????????? return canonicalName + "[]";
??????????? else
??????????????? return null;
??????? }
??????? if (isLocalOrAnonymousClass())
??????????? return null;
??????? Class<?> enclosingClass = getEnclosingClass();
??????? if (enclosingClass == null) { // top level class
??????????? return getName();
??????? } else {
??????????? String enclosingName = enclosingClass.getCanonicalName();
??????????? if (enclosingName == null)
??????????????? return null;
??????????? return enclosingName + "." + getSimpleName();
??????? }
??? }

  • isArray()

判斷該Class對象是否為數組,如果是返回true,不是返回false

  • getComponentType()

返回表示數組類型(元素類型)的類,如果該Class對象不是一個數組,則返回null

  • isLocalOrAnonymousClass()

該方法是一個私有方法,用來判斷該Class對象是否為本地類或匿名類

  • getEnclosingClass()

返回該Class對象的封裝類,如果是該Class對象是頂級類,則返回null

getSimpleName()

  • 返回源代碼中給出的基礎類的簡單名稱,如果基礎類是匿名的,則返回空字符串
  • 可以理解為返回的是僅僅是 類名,不包含路徑
  • 不能保證能唯一標識一個類,可以在toString()或日志操作期間使用

??? public String getSimpleName() {
??????? if (isArray())
??????????? return getComponentType().getSimpleName()+"[]";

??????? String simpleName = getSimpleBinaryName();
??????? if (simpleName == null) { // top level class
??????????? simpleName = getName();
??????????? return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name
??????? }
???
??????? int length = simpleName.length();
??????? if (length < 1 || simpleName.charAt(0) != '$')
??????????? throw new InternalError("Malformed class name");
??????? int index = 1;
??????? while (index < length && isAsciiDigit(simpleName.charAt(index)))
??????????? index++;
??????? // Eventually, this is the empty string iff this is an anonymous class
??????? return simpleName.substring(index);
??? }

  • getSimpleBinaryName()

該方法是一個私有方法,返回該Class對象的的“簡單二進制名稱”,如果該Class對象是頂級類,則返回null,用 BBB.class.getSimpleName() 為例,該方法會返回 $BBB

  • isAsciiDigit(char c)

該方法也是一個私有方法,用于判斷 getSimpleBinaryName() 返回的值下標為 1 處的字符是否位于 ‘0’ - ‘9’ 之間,如果是返回true且index遞增,不是返回false

用 new Object(){}.getClass().getSimpleName() 為例,使用 new Object(){}.getClass() 得到的結果為 class lang.reflect.AAA$1,再調用 getSimpleName(),最終會返回空字符串

getTypeName()

  • 返回此類型名稱的信息字符串
  • 可以理解為返回的是該類類型的名稱

修飾符

可以通過Class對象來訪問一個類的修飾符,即public,private,static等等的關鍵字,你可以使用如下方法來獲取類的修飾符

int modifier = clazzAnimal.getModifiers();System.out.println("getTypeName:" + modifier);Modifier.isAbstract(modifier);Modifier.isFinal(modifier);Modifier.isInterface(modifier);Modifier.isNative(modifier);Modifier.isPrivate(modifier);Modifier.isProtected(modifier);Modifier.isPublic(modifier);Modifier.isStatic(modifier);Modifier.isStrict(modifier);Modifier.isSynchronized(modifier);Modifier.isTransient(modifier);Modifier.isVolatile(modifier);

包信息、父類、實現的接口

//getPackage:study.reflectionjava.lang.Package aPackage = clazzAnimal.getPackage();System.out.println("getPackage:" + aPackage.getName());//getSuperclass:study.reflection.AnimalClass superclass = clazzHorse.getSuperclass();System.out.println("getSuperclass:" + superclass.getName());//getInterfaces -Animal:study.reflection.IRun;study.reflection.IEat;System.out.println("getInterfaces -Animal:" + printList( clazzAnimal.getInterfaces() ));//getInterfaces -Hourse:System.out.println("getInterfaces -Hourse:" + printList( clazzHorse.getInterfaces() ));

構造器

方法用途
getConstructor(Class...<?> parameterTypes)獲得該類中與參數類型匹配的公有構造方法
getConstructors()獲得該類的所有公有構造方法
getDeclaredConstructor(Class...<?> parameterTypes)獲得該類中與參數類型匹配的構造方法
getDeclaredConstructors()獲得該類所有構造方法
  • 構造方法參數

Class[] parameterTypes = constructor.getParameterTypes();?

  • ?利用Constructor對象實例化一個類

Constructor<?> con = clazzHorse.getConstructor(String.class);
Animal animal = (Animal)?? con.newInstance("horse");

?

方法

方法用途
getMethod(String name, Class...<?> parameterTypes)獲得該類某個公有的方法
getMethods()獲得該類所有公有的方法
getDeclaredMethod(String name, Class...<?> parameterTypes)獲得該類某個方法
getDeclaredMethods()獲得該類所有方法
  • 調用方法

Method method = clazzHorse.getMethod("run", null);
method.invoke(horse);

  • 方法參數以及返回類型?

Class[] parameterTypes = method.getParameterTypes();
Class returnType = method.getReturnType();?

字段

方法用途
getField(String name)獲得某個公有的屬性對象
getFields()獲得所有公有的屬性對象
getDeclaredField(String name)獲得某個屬性對象
getDeclaredFields()獲得所有屬性對象

注解

方法用途
getAnnotation(Class<A> annotationClass)返回該類中與參數類型匹配的公有注解對象
getAnnotations()返回該類所有的公有注解對象
getDeclaredAnnotation(Class<A> annotationClass)返回該類中與參數類型匹配的所有注解對象
getDeclaredAnnotations()返回該類所有的注解對象

getDeclaredXXX和getXXX的區別

getDeclaredMethod*()獲取的是類自身聲明的所有方法,包含public、protected和private方法。

getMethod*()獲取的是類的所有共有方法,這就包括自身的所有public方法,和從基類繼承的、從接口實現所有public方法。

類中其他重要的方法

方法用途
isAnnotation()如果是注解類型則返回true
isAnnotationPresent(Class<? extends Annotation> annotationClass)如果是指定類型注解類型則返回true
isAnonymousClass()如果是匿名類則返回true
isArray()如果是一個數組類則返回true
isEnum()如果是枚舉類則返回true
isInstance(Object obj)如果obj是該類的實例則返回true
isInterface()如果是接口類則返回true
isLocalClass()如果是局部類則返回true
isMemberClass()如果是內部類則返回true

數組

利用反射機制來處理數組會有點棘手。尤其是當你想要獲得一個數組的Class對象,比如int[]等等。

通過反射機制創建數組和獲取數組的Class對象。

java.lang.reflect.Array

Java反射機制通過java.lang.reflect.Array這個類來處理數組。不要把這個類與Java集合套件(Collections suite)中的java.util.Arrays混淆。

創建數組、訪問數組

int[] intArray = (int[]) Array.newInstance(int.class, 3);Array.set(intArray, 0, 123); Array.set(intArray, 1, 456); Array.set(intArray, 2, 789);System.out.println("intArray[0] = " + Array.get(intArray, 0)); System.out.println("intArray[1] = " + Array.get(intArray, 1)); System.out.println("intArray[2] = " + Array.get(intArray, 2));

?獲取數組的Class對象

  • 獲取數組的Class對象:

?? ?Class stringArrayClass = String[].class;

  • 如果使用Class.forName()方法來獲取Class對象

你可以像這樣來獲得一個原生數據類型(primitive)int數組的Class對象:

??? Class intArray = Class.forName("[I");


在JVM中字母I代表int類型,左邊的‘[’代表我想要的是一個int類型的數組,這個規則同樣適用于其他的原生數據類型。
對于普通對象類型的數組有一點細微的不同:

??? Class stringArrayClass = Class.forName("[Ljava.lang.String;");

注意‘[L’的右邊是類名,類名的右邊是一個‘;’符號。這個的含義是一個指定類型的數組。
需要注意的是,不能通過Class.forName()方法獲取一個原生數據類型的Class對象。
下面這兩個例子都會報ClassNotFoundException:

??? Class intClass1 = Class.forName("I");
?? ?Class intClass2 = Class.forName("int");

通常會用下面這個方法來獲取普通對象以及原生對象的Class對象:

??? public Class getClass(String className){
?? ?? if("int" .equals(className)) return int .class;
?? ?? if("long".equals(className)) return long.class;
?? ?? ...
?? ?? return Class.forName(className);
?? ?}

一旦獲取了類型的Class對象,你就有辦法輕松的獲取到它的數組的Class對象,你可以通過指定的類型創建一個空的數組,然后通過這個空的數組來獲取數組的Class對象。這樣做有點討巧,不過很有效。如下例:

??? Class theClass = getClass(theClassName);
?? ?Class stringArrayClass = Array.newInstance(theClass, 0).getClass();

這是一個特別的方式來獲取指定類型的指定數組的Class對象。無需使用類名或其他方式來獲取這個Class對象。
為了確保Class對象是不是代表一個數組,你可以使用Class.isArray()方法來進行校驗:

??? Class stringArrayClass = Array.newInstance(String.class, 0).getClass();
?? ?System.out.println("is array: " + stringArrayClass.isArray());

?

總結

以上是生活随笔為你收集整理的反射-Class的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。