IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Kotlin学习笔记 第四章 Java调用Kotlin -> 正文阅读

[移动开发]Kotlin学习笔记 第四章 Java调用Kotlin

参考链接

Kotlin官方文档

https://kotlinlang.org/docs/home.html

中文网站

https://www.kotlincn.net/docs/reference/properties.html

pdf也可以在这里下载

https://www.kotlincn.net/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成员方法
        // 注意 调用成员方法时使用D0509JavaCallKotlin
        D0509JavaCallKotlin 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 而不是D0509JavaCallKotlin
        D0509JavaCallKotlinKt.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.d05others

fun 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.d05others

fun myPrint2() {
    println("hello world2")
}

class MyPerson {
    var name: String = "zhangsan"

    // 2 @JvmField的使用
    // @JvmField 会将普通的实例变量 变化成 类变量
    // 即age1会变成一个静态变量 且没有set get方法
    @JvmField
    var age1: Int = 10
    var age2: Int = 20
}

class MyPeople {
    companion object {
        var name = "zhangsan"
        var age = 20

        // 3 @JvmField 修饰伴生对象的filed
        // age3变成伴生对象的类变量 没有了set get方法
        @JvmField
        var age3 = 30

        // 4 @JvmStatic修饰伴生对象的方法
        // 在Kotlin中 可以将剧名对象或者伴生对象中定义的函数注解为@JvmStatic 这样编译器会机会再相应对象的类中生成静态(类)方法 也会在在相应的类中生成实例方法
        // 即 在companion对象中生成test1方法 在MyPeople也生成test1方法 且MyPeople.test1方法内部调用的是companion.test1
        @JvmStatic
        fun 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(MyPeople.Companion.getAge());
        System.out.println(MyPeople.Companion.getName());
        // @JvmField加在伴生对象的属性上
        System.out.println(MyPeople.age3);

        MyPeople.Companion.test1();
        // @JvmStatic加在伴生对象的方法上
        MyPeople.test1();
        MyPeople.Companion.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注解 解决方法命名冲突2
class MyClass {
    val a: Int
        /**
         * Kotlin默认给属性a提供了get方法 签名为getA
         * 因此如果另外又定义了getA方法 则会产生命名冲突
         * 需要使用JvmName注解 将方法名改为另一个名字
         * 但是注意 这里的JvmName还是给Java类用的 不影响Kotlin自身调用 a 属性
         */
        @JvmName("getAValue")
        get() = 20

    fun 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而非myFilter2
    val 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注解 解决方法命名冲突2
        MyClass 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.d05others

import java.io.FileNotFoundException
import kotlin.jvm.Throws

class 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); //运行直接报错
    }
}

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-09-22 14:48:20  更:2021-09-22 14:49:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:36:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码