参考链接
Kotlin官方文档
/docs/home.html
中文网站
/docs/reference/properties.html
pdf也可以在这里下载
/docs/kotlin-docs.pdf
大部分示例来自bilibili Kotlin语言深入解析 张龙老师的视频
Part1
知识点
1 Kotlin属性 set get方法命名的变化
2 调用Kotlin成员方法
3 顶层空间的属性和方法属于静态方法
4 注意对比带Kt和不带Kt的类的使用
笔记
Kotlin class
/*** 属性 (properties)* 一个Kotlin的属性会被编译为3个部分* 1.一个get方法* 2.一个set方法* 3.一个私有field域(field)** 如果Kotlin的属性以is开头 那么set get方法会发生一些变化* get方法方法名与属性名一致* set方法会将is替换为set* 这种规则适用于所有类型的属性 不一定时Boolean类型*/class Test{var isStudent:String = "yes"}// 定义在顶层空间的属性和方法都是静态属性和方法fun test1() {println("test1")}var str: String = "hello"class D0509JavaCallKotlin {fun nonStaticMethod(){println("nonStaticMethod")}}
Java class CallKotlin
public class CallKotlin {public static void main(String[] args) {Test test = new Test();// 1 Kotlin属性 set get方法命名的变化test.setStudent("AAA");System.out.println(test.isStudent());System.out.println("--------- 1 end ----------");// 2 调用Kotlin成员方法// 注意 调用成员方法时使用D0509JavaCallKotlinD0509JavaCallKotlin aa = new D0509JavaCallKotlin();// D0509JavaCallKotlinKt bb = new D0509JavaCallKotlinKt();// 运行时报错 cannot find symbol// 我们无法通过new关键字创建由Kotlin编译器生成的以Kt结尾的类的示例// 因为在生成的字节码中 没有为以Kt结尾的类生成任何构造方法// 反而是对应的没有以Kt结尾的类 是有构造方法的aa.nonStaticMethod();System.out.println("--------- 2 end ----------");// 3 顶层空间的属性和方法属于静态方法// 注意 调用时使用D0509Java3 @JvmField 修饰伴生对象的filedCallKotlinKt 而不是D0509JavaCallKotlinD0509JavaCallKotlinKt.test1();D0509JavaCallKotlinKt.setStr("set str");System.out.println(D0509JavaCallKotlinKt.getStr());System.out.println("--------- 3 end ----------");// 4 注意对比带Kt和不带Kt的类的使用// 即 D0509JavaCallKotlinKt 与 D0509JavaCallKotlin}}
Part2
知识点
1 元注解@file的使用
2 @JvmField的使用
3 @JvmField 修饰伴生对象的filed
4 @JvmStatic修饰伴生对象的方法
笔记
Kotlin code
// @file 注解代表期望将当前文件的生成文件从D0509JavaCallKotlin2 修改为HelloWorld1@file: JvmMultifileClass@file: JvmName("HelloWorld1")package com.example.lib.d05othersfun myPrint(){println("hello world1")}class D0509JavaCallKotlin2 {}// 1 元注解@file的使用// 注解如果和D0509JavaCallKotlin2相同 且没有加 @file: JvmMultifileClass 则会报错// e: D:\testDarren\LearnKotlin\StartKotlin\lib\src\main\java\com\example\lib\d05others\D0509JavaCallKotlin2.kt: (1, 1): Duplicate JVM class name 'com/example/lib/d05others/HelloWorld1' generated from: HelloWorld1, HelloWorld1// 如果加上了 @file: JvmMultifileClass 则代表与其他叫HelloWorld1的文件进行合并@file: JvmMultifileClass@file: JvmName("HelloWorld1")package com.example.lib.d05othersfun myPrint2() {println("hello world2")}class MyPerson {var name: String = "zhangsan"// 2 @JvmField的使用// @JvmField 会将普通的实例变量 变化成 类变量// 即age1会变成一个静态变量 且没有set get方法@JvmFieldvar age1: Int = 10var age2: Int = 20}class MyPeople {companion object {var name = "zhangsan"var age = 20// 3 @JvmField 修饰伴生对象的filed// age3变成伴生对象的类变量 没有了set get方法@JvmFieldvar age3 = 30// 4 @JvmStatic修饰伴生对象的方法// 在Kotlin中 可以将剧名对象或者伴生对象中定义的函数注解为@JvmStatic 这样编译器会机会再相应对象的类中生成静态(类)方法 也会在在相应的类中生成实例方法// 即 在companion对象中生成test1方法 在MyPeople也生成test1方法 且MyPeople.test1方法内部调用的是companion.test1@JvmStaticfun test1() {println("test1")}fun test2() {println("test2")}}}class D0509JavaCallKotlin3 {}
Java code
package com.example.lib.d05others;public class CallKotlin2 {public static void main(String[] args) {// JvmName修改了生成的字节码文件名// 同时JvmMultifileClass可以合并不同字节码文件// 虽然Kotlin有这个功能 但是非必要不推荐使用HelloWorld1.myPrint();HelloWorld1.myPrint2();// JvmField使用使用在普通对象上// Java 调用普通对象MyPerson person = new MyPerson();System.out.println(person.getName());// age1变成了类变量System.out.println(person.age1);System.out.println(person.getAge2());// Java 调用伴生对象System.out.println(panion.getAge());System.out.println(panion.getName());// @JvmField加在伴生对象的属性上System.out.println(MyPeople.age3);panion.test1();// @JvmStatic加在伴生对象的方法上MyPeople.test1();panion.test2();}}
Part3
知识点
1 JvmName注解 解决方法命名冲突
2 JvmName注解 解决方法命名冲突2
3 Java调用Kotlin带有默认参数的构造方法
4 Java调用Kotlin带有默认参数的普通方法
笔记
Kotlin code
package com.example.lib.d05others/*** 1 JvmName注解 解决方法命名冲突** 由于类型擦除 (Java在生成的字节码文件中会抹去泛型信息) 以下两个方法在字节码的签名一致* 因此报错* Platform declaration clash: The following declarations have the same JVM signature* (myFilter(Ljava/util/List;)Ljava/util/List;)* 大意是 myFilter都接受一个List参数 返回一个List* (为什么会接受一个List参数? 这是因为Java没有扩展方法的概念 Kotlin的扩展方法的实现原理是将类的实例传入,然后调用该实例的方法* 因为这里是List的扩展方法 因此会将List实例作为参数传入扩展方法)** 要想让这两个方法同时存在 可以使用 @JvmName注解*/fun List<String>.myFilter(): List<String> {return listOf("hello", "world")}@JvmName("myFilter2")fun List<Int>.myFilter(): List<Int> {return listOf(1, 2, 3)}// 2 JvmName注解 解决方法命名冲突2class MyClass {val a: Int/*** Kotlin默认给属性a提供了get方法 签名为getA* 因此如果另外又定义了getA方法 则会产生命名冲突* 需要使用JvmName注解 将方法名改为另一个名字* 但是注意 这里的JvmName还是给Java类用的 不影响Kotlin自身调用 a 属性*/@JvmName("getAValue")get() = 20fun getA() = 30}/*** 3 Java调用Kotlin带有默认参数的构造方法* 如果没有加上@JvmOverloads* Java能调用的构造方法 只有两个参数的构造方法 无法省略参数* 加上@JvmOverloads后 编译的文件会生成一个参数的构造方法 该方法内部调用了两个参数的构造方法*/class MyClass5 @JvmOverloads constructor(x: Int, y: String = "hello") {// 4 Java调用Kotlin带有默认参数的普通方法// JvmOverloads注解同样适用于普通方法@JvmOverloads fun myMethod(a: Int, b: String, c: Int = 2) {println("a:$a,b:$b,c:$c")}}fun main() {// 1 JvmName注解 解决方法命名冲突 示例// 需要注意的是 这里的别名只给Java使用 在Kotlin中使用方法仍然应该使用myFilter而非myFilter2val list = listOf<Int>()println(list.myFilter())val list2 = listOf<String>()println(list2.myFilter())// 2 JvmName注解 解决方法命名冲突2 示例println(MyClass().getA())// 注意 这里调用a的方式和Java不同println(MyClass().a)println(MyClass5(1))}class D0509JavaCallKotlin4 {}
Java code
package com.example.lib.d05others;import java.util.ArrayList;import java.util.List;public class CallKotlin3 {public static void main(String[] args) {// 1 JvmName注解 解决方法命名冲突List<String> list = D0509JavaCallKotlin4Kt.myFilter(new ArrayList<String>());System.out.println(list);List<Integer> list2 = D0509JavaCallKotlin4Kt.myFilter2(new ArrayList<Integer>());System.out.println(list2);// 2 JvmName注解 解决方法命名冲突2MyClass myClass = new MyClass();System.out.println(myClass.getA());System.out.println(myClass.getAValue());// 3 Java调用Kotlin带有默认参数的构造方法MyClass5 myClass5 = new MyClass5(1,"string");// Java看起来也可以使用默认参数了MyClass5 myClass51 = new MyClass5(1);// 4 Java调用Kotlin带有默认参数的普通方法myClass5.myMethod(1,"string");myClass5.myMethod(1,"string",2);}}
Part4
知识点
1 Java调用Kotlin抛出检查时异常的方法
2 Java调用Kotlin抛出检查时异常的方法(Java不异常终止)
3 Java调用Kotlin时 空保护失效
笔记
Kotlin code
package com.example.lib.d05othersimport java.io.FileNotFoundExceptionimport kotlin.jvm.Throwsclass D0509JavaCallKotlin5 {/*** 1 Java调用Kotlin抛出检查时异常的方法* 因为Kotlin没有checked exception 因此Java调用该方法时 认为该方法是普通方法* 可以直接调用 然而却在运行时抛出异常 且method invoked 都不会输出*/fun method(){println("method invoked")throw FileNotFoundException("file not found")}/*** 2 Java调用Kotlin抛出检查时异常的方法(Java不异常终止)* @Throws 注解告诉Java文件 该方法会抛出异常*/@Throws(FileNotFoundException::class)fun method2(){println("method invoked")throw FileNotFoundException("my file not found")}/*** 3 Java调用Kotlin时 空保护失效* 这里str在Kotlin明显是一个非空的string* 然而Java调用时并不知道这一点* 如果直接传入空 会被Kotlin在判空检查时就检查出来 因此method3 invoked都不会输出 直接抛出异常*/fun method3(str:String){println("method3 invoked")println(str)}}
Java code
import java.io.FileNotFoundException;public class CallKotlin4 {public static void main(String[] args) {D0509JavaCallKotlin5 kotlin5 = new D0509JavaCallKotlin5();// kotlin5.method();// 运行时报错// 因为加了@Throws注解 Java调用时知道该方法可能抛出异常try {kotlin5.method2();} catch (FileNotFoundException e) {System.out.println("catch FileNotFoundException "+e.getMessage());}kotlin5.method3("hello");// kotlin5.method3(null); //运行直接报错}}