Kotlin中与Java互操作与可空性、类型映射、属性访问、@JvmOverloads、@JvmField、@JvmStatic、@Throws和函数类型操作详解

博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家
点击跳转到教程

一、Kotlin与Java互操作与可空性。

Kotlin与Java互操作性与可空性
Java世界里所有对象都可能是null,当一个Kotlin函数返回String类型值,你不能想当然地认为
它的返回值就能符合Kotlin关于空值的规定。

1、首先定义一个Java类

public class Jhava {
    public String utterGreeting() {
        return "hello";
    }

    public String determineFriendshipLevel() {
        return null;
    }
}

2、Kotlin代码调用Java代码

fun main() {
    /**
     * Kotlin与Java互操作性与可空性
     * Java世界里所有对象都可能是null,当一个Kotlin函数返回String类型值,你不能想当然地认为
     * 它的返回值就能符合Kotlin关于空值的规定。
     */
    val adversary = Jhava()
    println(adversary.utterGreeting())
    /**
     * 返回 String! 类型的值,这里的感叹号表示返回值是String或者String?
     * 至于Java方法返回的是String类型值是null还是其他什么,Kotlin编译器并不知道。
     * 这种模棱两可的返回值类型,我们称之为平台类型。
     */
    var level = adversary.determineFriendshipLevel()
    /**
     * null值问题最有可能来自互操作,所以从kotlin里调用Java代码时,一定要小心谨慎。
     */
    println(level?.toLowerCase())
}

输出结果如下

hello
null

二、类型映射、属性访问、@JvmOverloads详解

public class Jhava {

    private int age = 18;
    public int num = 1;

    public String utterGreeting() {
        return "hello";
    }

    public String determineFriendshipLevel() {
        return null;
    }

    public int getAge() {
        System.out.println("------getAge()-----");
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public static void main(String[] args) {
        /**
         * Kotlin顶层函数在Java里都被当作静态方法看待和调用。
         */
        System.out.println(Hero.makeProclamation());
        Spellbook spellbook = new Spellbook();
        List<String> spells = spellbook.spells;
        System.out.println(spells);
        /**
         * Java要支持
         */
        Hero.handOverFood("apple");
    }
}
/**
 * 可以使用@JvmName注解指定编译类的名字。
 * 必须放在包名上面,否则报错。
 */
@file:JvmName("Hero")

package com.example.kotlinlearn.kotlin06

/**
 * @Author: ly
 * @Date: 2023/2/8
 * @Description:
 */

fun main() {
 	val adversary = Jhava()
	/**
     * 代码运行时,所有的映射类型都会重新映射成对应的Java类型
     */
    println(adversary.num.javaClass)
    /**
     * 属性访问
     * 不需要调用相关setter方法,你可以使用赋值语法来设置一个Java字段值。
     */
    println(adversary.age)
    adversary.age = 40
    println(adversary.age)
    handOverFood("apple")
}

fun makeProclamation() = "Greeting,best!"

/**
 * @JvmOverloads 注解协助产生Kotlin函数的重载版本。设计一个可能会暴露给Java用户使用API时,记得使用
 * @JvmOverloads 注解,这样,无论你是Kotlin开发者还是Java开发者,都会对这个API的可靠性感到满意。
 */
@JvmOverloads
fun handOverFood(leftHand: String = "berries", rightHand: String = "beef") {
    println("Mmm you hand over some delicious $leftHand and $rightHand")
}

输出结果如下

int
------getAge()-----
18
------getAge()-----
40
Mmm you hand over some delicious apple and beef

三、@JvmField详解

1、使用Kotlin创建一个类

class Spellbook {
    /**
     * 在Java里,不能直接访问spells字段,所以必须调用getSpells,然而,你可以给
     * Kotlin属性添加@JvmField注解,暴露它的支持字段给Java调用者,从而避免用getter方法。
     */
    @JvmField
    val spells = listOf("Magic Ms.L", "Lay on Hans")
}

2、使用Java创建一个Person类

public class Person{
public static void main(String[] args) {
        Spellbook spellbook = new Spellbook();
        List<String> spells = spellbook.spells;
        System.out.println(spells);
    }
}

输出结果如下

[Magic Ms.L, Lay on Hans]

四、@JvmStatic、@Throws和函数类型操作

class Student {
    companion object {
        /**
         * @JvmField 注解还能用来以静态方式提供伴生对象来定义的值。
         */
        @JvmField
        val STUDENT_NAME = "Android"

        /**
         * @JvmStatic 注解的作用类似于@JvmField,允许你直接调用伴生对象里的函数。
         */
        @JvmStatic
        fun study() = "I am study Android development"
    }
}

fun main() {
    //Kotlin中所有的异常都是默认不捕获的,当然也可以手动添加try catch进行捕获
//    Grade().doSomething()
    try {
        Grade().doSomething()
    } catch (e: Exception) {
        println("Java IOException")
    }

    println("测试")
    ktExceptionMethod()
}

/**
 * @Throws
 * 抛出一个需要检查的异常,Java和Kotlin有关异常检查的差异让@Throws注解给解决掉了,
 * 在编写供Java开发者调用的KotlinAPI时,要考虑使用@Throws注解,这样用户就知道怎么正确处理异常了。
 */
@Throws(IOException::class)
fun ktExceptionMethod() {
    throw IOException()
}

val major = { majorName: String, majorContent: String ->
    println("$majorName study $majorContent")
}

输出结果如下

Java IOException
测试
Exception in thread "main" java.io.IOException
	at com.example.kotlinlearn.kotlin06.StudentKt.ktExceptionMethod(Student.kt:47)
	at com.example.kotlinlearn.kotlin06.StudentKt.main(Student.kt:37)
	at com.example.kotlinlearn.kotlin06.StudentKt.main(Student.kt)

Java类如下

public class Grade {
    public static void main(String[] args) {
        System.out.println(Student.STUDENT_NAME);
        System.out.println(Student.study());
        try {
            new Grade().doSomething();
        } catch (IOException e) {
            System.out.println("IOException");
        }
        System.out.println("test");
        try {
            StudentKt.ktExceptionMethod();
        } catch (IOException e) {
            System.out.println("kotlin exception");
        }
        /**
         * 函数类型和匿名函数能提供高效的语法用于组件间的交互,是Kotlin编程语言里比较新颖的特性。
         * 它们简洁的语法因->操作符而实现,但Java8之前的JDK版本并不支持lambda表达式。
         * 在Java里,Kotlin函数类型使用FunctionN这样的名字的接口来表示的,FunctionN中的N代表值参数目。
         * 这样的Function接口有23个,从Function0到Function22,每一个FunctionN都包含一个invoke函数,专用于
         * 调用函数类型函数,所以,任何时候需要调一个函数类型,都要它调用invoke()方法。
         */
        Function2<String, String, Unit> major = StudentKt.getMajor();
        major.invoke("computer", "Knock the code");
    }

    public void doSomething() throws IOException {
        throw new IOException();
    }
}

输出结果如下

Android
I am study Android development
IOException
test
kotlin exception
computer study Knock the code

你可能感兴趣的:(kotlin笔记,java,kotlin,android,互操作,可空性)