本篇文章給大家分享的是有關(guān)Kotlin中反射機制的原理是什么,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
創(chuàng)新互聯(lián)網(wǎng)站建設(shè)提供從項目策劃、軟件開發(fā),軟件安全維護(hù)、網(wǎng)站優(yōu)化(SEO)、網(wǎng)站分析、效果評估等整套的建站服務(wù),主營業(yè)務(wù)為網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè),重慶APP軟件開發(fā)以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。創(chuàng)新互聯(lián)深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!Java中的反射機制,使得我們可以在運行期獲取Java類的字節(jié)碼文件中的構(gòu)造函數(shù),成員變量,成員函數(shù)等信息。這一特性使得反射機制被常常用在框架中,想要比較系統(tǒng)的了解Kotlin中的反射,先從Java的反射說起。
Java中的反射
通常我們寫好的.java源碼文件,經(jīng)過javac的編譯,最終生成了.class字節(jié)碼文件。這些字節(jié)碼文件是與平臺無關(guān)的,使用時通過Classloader去加載這些.class字節(jié)碼文件,從而讓程序按照我們編寫好的業(yè)務(wù)邏輯運行。Java的反射主要是從這些.class文件中獲取我們想要得到的內(nèi)容,那么Java中的反射能夠得到哪些內(nèi)容呢?
獲取Class對象
Java是面向?qū)ο蟮恼Z言,同樣的.class字節(jié)碼文件也不例外,想要獲取.class文件中的內(nèi)容,就要先獲取.class文件對應(yīng)的Class對象。Java中獲取Class對象的方式有三種。
//1.Class.forName("類名字符串") (注意:類名字符串必須是全稱,包名+類名) Class baseInfo = Class.forName("top.sguotao.ReflectionJava"); //2.類名.class Class object = Object.class; //3.實例對象.getClass() Class date = (new Date()).getClass(); Class testclass = this.getClass();
獲取類的構(gòu)造函數(shù)Constructor
獲取Class對象之后,就可以獲取其中的構(gòu)造函數(shù),從而去創(chuàng)建實例對象。類的構(gòu)造函數(shù)對應(yīng)java.lang.reflect.Constructor。獲取構(gòu)造函數(shù)歸納起來有以下五種方式:
// 1.獲取參數(shù)列表是parameterTypes,訪問控制符是public的構(gòu)造函數(shù) public Constructor getConstructor(Class[] parameterTypes) // 2.獲取所有訪問控制符是public的構(gòu)造函數(shù) public Constructor[] getConstructors() // 3.獲取參數(shù)列表是parameterTypes,并且是類自身聲明的構(gòu)造函數(shù),訪問控制符包含public、protected和private的函數(shù)。 public Constructor getDeclaredConstructor(Class[] parameterTypes) //4.獲取類自身聲明的全部的構(gòu)造函數(shù),訪問控制符包含public、protected和private的函數(shù)。 public Constructor[] getDeclaredConstructors() //5.如果類聲明在其它類的構(gòu)造函數(shù)中,返回該類所在的構(gòu)造函數(shù),如果存在則返回,不存在返回null public Constructor getEnclosingConstructor()
獲取類的成員變量
類的成員變量對應(yīng)的是java.lang.reflect.Field,獲取成員變量歸納起來有以下四種方式:
//1.獲取“名稱是name”的public的成員變量(包括從基類繼承的、從接口實現(xiàn)的所有public成員變量) public Field getField(String name) //2.獲取全部的public成員變量(包括從基類繼承的、從接口實現(xiàn)的所有public成員變量) public Field[] getFields() //3.獲取“名稱是name”,并且是類自身聲明的成員變量,包含public、protected和private成員變量。 public Field getDeclaredField(String name) //4.獲取全部的類自身聲明的成員變量,包含public、protected和private成員變量。 public Field[] getDeclaredFields()
獲取類的成員函數(shù)
類的成員函數(shù)對應(yīng)的是java.lang.reflect.Method,獲取成員函數(shù)歸納起來有下面5種方式:
// 1.獲取函數(shù)名是name,參數(shù)是parameterTypes的public的函數(shù)(包括從基類繼承的、從接口實現(xiàn)的所有public函數(shù)) public Method getMethod(String name, Class[] parameterTypes) //2.獲取全部的public的函數(shù)(包括從基類繼承的、從接口實現(xiàn)的所有public函數(shù)) public Method[] getMethods() //3.獲取函數(shù)名name,參數(shù)是parameterTypes,并且是類自身聲明的函數(shù),包含public、protected和private方法。 public Method getDeclaredMethod(String name, Class[] parameterTypes) //4.獲取全部的類自身聲明的函數(shù),包含public、protected和private方法。 public Method[] getDeclaredMethods() //5.如果這個類是其它類中某個方法的內(nèi)部類,調(diào)用getEnclosingMethod()就是這個類所在的方法;若不存在,返回null。 public Method getEnclosingMethod()
獲取類的其它信息
獲取類的注解信息,對應(yīng)的是java.lang.annotation.Annotation接口,獲取類的注解信息歸納起來有下面3種方法:
//1.獲取類的annotationClass類型的注解 (包括從基類繼承的、從接口實現(xiàn)的所有public成員變量) public Annotation getAnnotation(Class annotationClass) //2.獲取類的全部注解 (包括從基類繼承的、從接口實現(xiàn)的所有public成員變量) public Annotation[] getAnnotations() //3.獲取類自身聲明的全部注解 (包含public、protected和private成員變量) public Annotation[] getDeclaredAnnotations()
獲取類的接口和基類的信息,對應(yīng)的是java.lang.reflect.Type接口,獲取類的接口和基類信息有下面兩個方法:
// 獲取實現(xiàn)的全部接口 public Type[] getGenericInterfaces() // 獲取基類 public Type getGenericSuperclass()
獲取類的其它描述信息。
//1.獲取類名 public String getSimpleName() //2.獲取完整類名 public String getName() //3.判斷類是不是枚舉類 public boolean isEnum() //4.判斷obj是不是類的實例對象 public boolean isInstance(Object obj) //5.判斷類是不是接口 public boolean isInterface() //6.判斷類是不是本地類,所謂本地類,就是定義在方法內(nèi)部的類。 public boolean isLocalClass() //7.判斷類是不是成員類,所謂成員類,就是常見的內(nèi)部類,是指不在代碼塊,構(gòu)造函數(shù)和成員方法中的內(nèi)部類。 public boolean isMemberClass() //8.判斷類是不是基本類型。 基本類型,包括void和boolean、byte、char、short、int、long、float 和 double這幾種類型。 public boolean isPrimitive()
Kotlin中的反射
在Kotlin中,字節(jié)碼對應(yīng)的類是kotlin.reflect.KClass,因為Kotlin百分之百兼容Java,所以Kotlin中可以使用Java中的反射,但是由于Kotlin中字節(jié)碼.class對應(yīng)的是KClass類,所以如果想要使用Java中的反射,需要首先獲取Class的實例,在Kotlin中可以通過以下兩種方式來獲取Class實例。
//1.通過實例.javaClass var hello = HelloWorld() hello.javaClass //2.通過類Kclass類的.java屬性 HelloWorld::class.java
獲取了Class實例,就可以調(diào)用上面介紹的方法,獲取各種在Java中定義的類的信息了。
當(dāng)然Kotlin中除了可以使用Java中的反射以外,還可以使用Kotlin中聲明的一些方法,當(dāng)然同Java中反射一樣,想要使用這些方法,先要獲取Kclass對象,在Kotlin中可以通過以下兩種方式獲取Kclass實例。
//1.通過類::class的方式獲取Kclass實例 val clazz1: KClass<*> = HelloWorld::class //2.通過實例.javaClass.kotlin獲取Kclass實例 var hello = HelloWorld() val clazz2 = hello.javaClass.kotlin
獲取了Kclass實例之后,就可以調(diào)用Kotlin中聲明的一些關(guān)于反射的方法了,那么都有哪些方法呢?
構(gòu)造函數(shù)Constructor
Kotlin可以通過下面的方法,獲取所有的構(gòu)造函數(shù)。
//返回這個類的所有構(gòu)造器 public val constructors: Collection>
成員變量和成員函數(shù)
Kotlin中獲取成員變量和成員函數(shù)的方法有6個。
//返回類可訪問的所有函數(shù)和屬性,包括繼承自基類的,但是不包括構(gòu)造器 override val members: Collection> //返回類聲明的所有函數(shù) val KClass<*>.declaredFunctions: Collection > //返回類的擴展函數(shù) val KClass<*>.declaredMemberExtensionFunctions: Collection > //返回類的擴展屬性 val KClass .declaredMemberExtensionProperties: Collection > //返回類自身聲明的成員函數(shù) val KClass<*>.declaredMemberFunctions: Collection > //返回類自身聲明的成員變量(屬性) val KClass .declaredMemberProperties: Collection >
類相關(guān)信息
可以看到Kotlin反射中,可以獲取比Java反射更多的關(guān)于類的信息。
//1.返回類的名字 public val simpleName: String? //2.返回類的全包名 public val qualifiedName: String? //3.如果這個類聲明為object,則返回其實例,否則返回null public val objectInstance: T? //4.返回類的可見性 @SinceKotlin("1.1") public val visibility: KVisibility? //5.判斷類是否為final類(在Kotlin中,類默認(rèn)是final的,除非這個類聲明為open或者abstract) @SinceKotlin("1.1") public val isFinal: Boolean //6.判斷類是否是open的(abstract類也是open的),表示這個類可以被繼承 @SinceKotlin("1.1") public val isOpen: Boolean //7.判斷類是否為抽象類 @SinceKotlin("1.1") public val isAbstract: Boolean //8.判斷類是否為密封類,密封類:用sealed修飾,其子類只能在其內(nèi)部定義 @SinceKotlin("1.1") public val isSealed: Boolean //9.判斷類是否為data類 @SinceKotlin("1.1") public val isData: Boolean //10.判斷類是否為成員類 @SinceKotlin("1.1") public val isInner: Boolean //11.判斷類是否為companion object @SinceKotlin("1.1") public val isCompanion: Boolean //12.返回類中定義的其他類,包括內(nèi)部類(inner class聲明的)和嵌套類(class聲明的) public val nestedClasses: Collection> //13.判斷一個對象是否為此類的實例 @SinceKotlin("1.1") public fun isInstance(value: Any?): Boolean //14.返回這個類的泛型列表 @SinceKotlin("1.1") public val typeParameters: List //15.類其直接基類的列表 @SinceKotlin("1.1") public val supertypes: List //16.返回類所有的基類 val KClass<*>.allSuperclasses: Collection > //17.返回類的伴生對象companionObject val KClass<*>.companionObject: KClass<*>?
使用Kotin中反射注意的問題
在Kotlin1.1中如果反射String,Map,List等類型時,會拋出一個built-in Kotlin Types的異常,這是因為在Kotlin1.1版本中還沒有對這些類型添加支持,在Kotlin1.2版本中,這個問題已經(jīng)解決。
Kotlin關(guān)于反射的內(nèi)容都放在kotlin-reflect的jar包中,這個jar包有2.6M,對于移動端開發(fā),需要占用一定的內(nèi)存空間。
最后就是關(guān)于Kotlin反射的效率問題,在Java中反射大概需要幾十微秒,在Kotlin就需要幾百甚至上千微秒,如果是通過反射訪問對象或構(gòu)造屬性,甚至需要上萬微秒,對此,官方給出的解釋是,現(xiàn)在還沒有精力進(jìn)行優(yōu)化,相信后續(xù)的版本中,效率問題會有所改善。
以上就是Kotlin中反射機制的原理是什么,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降摹OM隳芡ㄟ^這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。