@JvmStatic 告訴jvm生成靜態(tài)方法和成員
@JvmOverloads 生成Java重載方法,應(yīng)用于kotlin方法有默認(rèn)值生成對(duì)于的java方法
@JvmName 改變getter和setter中的方法名
@JvmField 直接暴露類中的屬性和
@Throws 聲明這個(gè)方法要檢查Exception
1.JvmOverloads
創(chuàng)建一個(gè)kotlin的類
class Student(val name: String, val sex: Int = 1, val age: Int = 18)
可以看出來(lái) 這個(gè)構(gòu)造函數(shù)的參數(shù)是有默認(rèn)值的,kotlin的特性對(duì)吧,我們?cè)谑褂玫臅r(shí)候可以方便的使用,比如:
val student = Student("wuyue")
val student2 = Student("wuyue", age = 18)
但是這個(gè)特性如果你用java來(lái)調(diào)用你就是失敗的了。
注意看下面的方法調(diào)用是報(bào)錯(cuò)的,不能調(diào),只能選擇3個(gè)構(gòu)造函數(shù)的方法。
那我一定要讓java也可以調(diào)用 怎么辦? 加上注解即可:
class Student @JvmOverloads constructor(val name: String, val sex: Int = 1, val age: Int = 18)
這個(gè)對(duì)于android程序員來(lái)說(shuō)還是很重要的,比如我們自定義view中 就需要這個(gè)注解,否則運(yùn)行起來(lái) 會(huì)因?yàn)檎也坏椒椒ǘ鴪?bào)錯(cuò)的。
所以大家只要謹(jǐn)記一點(diǎn): 當(dāng)你的kotlin代碼中的某個(gè)方法使用了 默認(rèn)參數(shù)值 這個(gè)kotlin語(yǔ)言的特性并且這個(gè)方法還要給java代碼調(diào)用的時(shí)候那你最好加上JvmOverloads 注解
2.JvmName
我們給String 增加一個(gè)擴(kuò)展函數(shù) StringsHelper.kt 文件
package com.test
fun String.appendUserName():String{
return this+"wuyue"
}
在kotlin里 怎么調(diào)用他呢?
StringsHelperKt.appendUserName("hello");
很好理解對(duì)吧, 但是很多人都習(xí)慣于在java的世界中 使用什么xxxUtils 去處理類似的情況。這個(gè)時(shí)候就要利用到這個(gè)JvmName了
@file:JvmName("StringsHelperUtils")
package com.test
fun String.appendUserName():String{
return this+"wuyue"
}
如此一來(lái) 我們?cè)趈ava的世界中 調(diào)用他的方法就變成了
StringsHelperUtils.appendUserName("hello");
3.JvmMultifileClass
關(guān)于這個(gè)注解 網(wǎng)上的說(shuō)法是 可以將2個(gè)kt文件 里面的代碼 合并到一個(gè)java的class文件中。
FunA.kt
@file:JvmName("Utils")
@file:JvmMultifileClass
package com.test
fun one(){
}
FunB.kt
@file:JvmName("Utils")
@file:JvmMultifileClass
package com.test
fun two(){
}
這樣在java世界中 調(diào)用Utils這個(gè)類 就有one和two 2個(gè)方法了,但是我自己的實(shí)驗(yàn)結(jié)果 我就算去掉這個(gè)JvmMultifileClass 這個(gè)注解也一樣可以達(dá)到效果。似乎這個(gè)注解并沒(méi)有什么用? 可能是1.3之后的kotlin版本 優(yōu)化了 JvmName的實(shí)現(xiàn)吧。 這里有知道原因的大佬可以指點(diǎn)一下。
4.JvmField
還是前面這個(gè)Student的例子
class Student( val name: String, val sex: Int = 1, val age: Int = 18)
如果在java代碼里 你要調(diào)用他里面的屬性 只能通過(guò)get和set 來(lái)調(diào)用。 但是如果你加上注解
class Student(@JvmField val name: String, val sex: Int = 1, val age: Int = 18)
那他在java的世界中就可以 直接調(diào)用了
student.name="hello";
另外還有一個(gè)重要的作用是: 在kotlin中, val 并不意味著是常量,只不過(guò)val 聲明的變量 是沒(méi)有set方法的,只有g(shù)et方法。所以給了你一個(gè)常量的錯(cuò)覺(jué)。 你要真正的 在kotlin中 定義一個(gè)常量,只有兩種方法:
1.在top-level或者object中 使用 const val
2.或者使用 @JvmField val(這種方式定義的就是常量了,講白了你也無(wú)法重寫val的get方法了)
5.JvmStatic
class StaticTest{
companion object{
const val field1="111"
val field2="222"
@JvmField val field3="333"
fun callNonStatic(){
}
@JvmStatic
fun callStatic(){
}
}
}
我們看一下 在java代碼中 怎么調(diào)用他們 就知道這個(gè)注解的實(shí)際作用了
StaticTest.callStatic();
StaticTest.Companion.callNonStatic();
String t1 = StaticTest.field1;
String t2=StaticTest.Companion.getField2();
String t3=StaticTest.field3;
6.JvmSynthetic
這個(gè)注解用的不多,但是kotlin的許多官方庫(kù)會(huì)用到他 講白了 如果你寫的一個(gè)函數(shù)你只想給kotlin代碼調(diào)用 而不想給java的代碼調(diào)用 那你就在你的函數(shù)上面加上這個(gè)注解即可
例如:
@file:JvmName("StringsHelperUtils")
package com.test
@JvmSynthetic
fun String.appendUserName():String{
return this+"wuyue"
}
這樣你就會(huì)發(fā)現(xiàn) 這個(gè)函數(shù) 你用kotlin正常使用 而java代碼里StringsHelperUtils 這個(gè)類 是沒(méi)有這個(gè)方法的
7.@Throws
java需要在每行代碼生成的地方都檢查異常,要嗎處理掉,要嗎網(wǎng)上拋,直到最頂上被頂級(jí)異常捕獲掉,最差的情況就是沒(méi)有捕獲這個(gè)異常,直至程序異常崩潰掉。
而在kotlin上,是不需要每步檢查異常的。這就導(dǎo)致了kotlin寫的代碼在java中調(diào)用不管有沒(méi)有拋出異常都不需要聲明或者捕獲異常。這樣肯定是有問(wèn)題的。為處理這個(gè)問(wèn)題就有了@Throws的用武之地。
//kotlin
@JvmStatic
fun saveAs(path: String?) {
val outputFile = File(path)
if (!outputFile.canWrite()) {
throw FileNotFoundException("Could not write to file: $path")
}
// Write data...
}
//java
public static void backupUsers() {
try {
if (!Repository.saveAs(Repository.BACKUP_PATH)) {
// TODO: Report error backing up user database.
}
} catch (IOException e) {
// Log exception.
}
}
強(qiáng)行在java中聲明異常會(huì)報(bào)錯(cuò),所以需要加注解處理
@JvmStatic
@Throws(IOException::class)
fun saveAs(path: String?) {
val outputFile = File(path)
if (!outputFile.canWrite()) {
throw FileNotFoundException("Could not write to file: $path")
}
// Write data...
}