反射和註解html
反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性,這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。 Kotlin中使用反射功能所需的運行時組件做爲單獨的 JAR 文件(kotlin-reflect.jar)分發。這樣作是爲了減小不使用反射功能的應用程序所需的運行時庫的大小。若是用Android Studio運行Kotlin項目,通常會在建立工程時,自動引入(kotlin-reflect.jar)java
//方式一
Class<?> clazz = User.class;
//方式二
Class<?> clazz = Class.forName("包名.User");
複製代碼
//若是User是Kotlin的類
var user = User::class
//若是User是Java的類
var user = User::class.java
複製代碼
在Kotlin中,用類名+兩個冒號::
+class(若是是java類要在後面加上.java)表示獲取這個類的對象。api
public class User {
private String userName;
public User(String userName) {
super();
this.userName = userName;
}
public void printUserName() {
System.out.println(userName);
}
}
//獲取User對象
Class<?> clazz = Class.forName("com.demo.czh.myapplication.User");
//獲取帶String參數的public構造函數
Constructor c=clazz.getDeclaredConstructor(String.class);
//建立User對象的實例
User user = (User) c.newInstance("Czh");
//根據方法名"printUserName"獲取 method 對象
Method method = clazz.getDeclaredMethod("printUserName");
//經過 method 調用 invoke()方法,調用User裏的 printUserName
method.invoke(user);
複製代碼
運行代碼,獲得結果:數組
class User(var userName: String) {
fun printUserName() {
println(userName)
}
}
//方式一
//獲取printUserName函數對象
var p = User::printUserName
//調用invoke()函數執行printUserName函數
p.invoke(User("Czh"))
//方式二
//利用Java反射機制調用getMethod()方法,並指定方法名字"printUserName"
var method = User::class.java.getMethod("printUserName")
//調用invoke()函數
method.invoke(User("Czh"))
複製代碼
運行代碼,獲得結果:bash
在Kotlin中,能夠用類名+兩個冒號::
+函數名直接獲取這個函數的對象;或者利用Java反射機制調用getMethod()
方法來獲取函數的對象。微信
public class User {
public String userName;
}
//獲取User對象
Class<?> clazz = Class.forName("com.demo.czh.myapplication.User");
//建立User對象的實例
User user = (User) clazz.newInstance();
//獲取Field對象並指定屬性名爲"userName"
Field field = clazz.getField("userName");
//經過set()方法給userName賦值
field.set(user, "Czh");
//經過get()方法獲取userName的值
System.out.println(field.get(user));
複製代碼
運行代碼,獲得結果:app
class User {
var userName: String = "Czh"
get() = field
set(value) {
field = value
}
}
//方式一
var user = User()
//獲取屬性對象
var userName = User::userName
println(userName.get(user))
//設置屬性值
userName.set(user, "James")
//獲取屬性值
println(userName.get(user))
//方式二
//利用Java反射機制獲取getUserName方法
var getName = User::class.java.getMethod("getUserName")
//利用Java反射機制獲取setUserName方法
var setName = User::class.java.getMethod("setUserName", java.lang.String().javaClass)
//設置屬性值
setName.invoke(user, "Harden")
//獲取屬性值
println(getName.invoke(user))
複製代碼
運行代碼,獲得結果:jvm
::
+屬性名直接獲取屬性對象;或者經過Java反射機制獲取屬性的
get/set
方法來獲取或修改屬性值。
Java聲明註解函數
public @interface MyAnnotation {
}
複製代碼
Kotlin聲明註解post
annotation class MyAnnotation
複製代碼
註解的附加屬性能夠經過用元註解標註註解類來指定:
@Target
指定能夠用該註解標註的元素的可能的類型(類、函數、屬性、表達式等);@Retention
指定該註解是否存儲在編譯後的 class 文件中,以及它在運行時可否經過反射可見 (默認都是 true);@Repeatable
容許在單個元素上屢次使用相同的該註解;@MustBeDocumented
指定該註解是公有 API 的一部分,而且應該包含在生成的 API 文檔中顯示的類或方法的簽名中。Java添加元註解
@Target(ElementType.METHOD)//表示能夠在方法中使用
@Retention(RetentionPolicy.RUNTIME)//表示運行時註解
public @interface MyAnnotation {
}
複製代碼
Kotlin添加元註解
@Target(AnnotationTarget.FUNCTION)//表示能夠在函數中使用
@Retention(AnnotationRetention.RUNTIME)//表示運行時註解
annotation class MyAnnotation
複製代碼
註解類能夠帶有構造函數
annotation class MyAnnotation(val value: Int)
//使用
@MyAnnotation(1)
class Foo {
}
複製代碼
public @interface MyAnnotation {
int value();
}
//使用
@MyAnnotation(1)
public class Foo {
}
複製代碼
註解類的構造函數只容許下列參數類型:
註解和反射都是不少應用中使用到的技術,而本篇文章主要對比了註解和反射在Java和Kotlin中寫法的差異。
參考文獻:
Kotlin語言中文站、《Kotlin程序開發入門精要》
推薦閱讀:
從Java到Kotlin(一)爲何使用Kotlin
從Java到Kotlin(二)基本語法
從Java到Kotlin(三)類和接口
從Java到Kotlin(四)對象與泛型
從Java到Kotlin(五)函數與Lambda表達式
從Java到Kotlin(六)擴展與委託
從Java到Kotlin(七)反射和註解
從Java到Kotlin(八)Kotlin的其餘技術
Kotlin學習資料總彙
更多精彩文章請掃描下方二維碼關注微信公衆號"AndroidCzh":這裏將長期爲您分享原創文章、Android開發經驗等! QQ交流羣: 705929135