Kotlin基础知识6

泛型与类型约束

open class MyAnyClass(name: String)
opne class PersonClass (name: String): MyAnyClass(name = name)
class StudentClass (name: String): PersonClass(name = name)

class Test<T: PersonClass>(private val inputTypeValue :T,private val isR:Boolean=true){
  fun getObj():T? = inputTypeValue.takeIf{isR}
}

可变参数

fun main() {
    foo("1","2","3")
}

fun foo(vararg args:String){
    println(args::class)
    println(args.contentToString())
    for (i in args.indices){
        println(args[i])
    }
    bar(args)
    bar1(*args)
}

fun bar(args: Array<out String>){
    println(args.contentToString())
}

fun bar1(vararg args:String){
    println(args.contentToString())
}
//output:
class kotlin.Array
[1, 2, 3]
1
2
3
[1, 2, 3]
[1, 2, 3]
//1.可变参数会在函数体中,自动转变为数组类型
//2.数组类型不能作为参数,直接传递给可变参数
//3.在数组类型前面添加*,可以传递给可变参数
//4.java中可变参数与数组可以直接互传

[]操作符与get函数


class test <INPUT> (vararg objects: INPUT, val isR: Boolean = true) {

    // 运算符重载
    operator fun get(index: Int) : INPUT ? = objectArray[index].takeIf { isR }
}
fun main() {

    // 只要有一个元素是null,那么所有的元素都是 String?
    val p1 : test<String?> = test("张三", "李四", "王五", null)

    var r : String? = p1[0]//如果一个自定义类想要使用[]操作符,就必须重载get方法
    val r2 : String ? = p1[3]

    println(r)
    println(p1[1])
    println(p1[2])
    println(r2)
}

out-协变


// 生产者 out T  协变 [out T 此泛型能够被获取 读取 所以是out]
interface Producer<out T> {

    // out T  代表整个生产者类里面  这个T  只能被读取,不能被修改了

    // 不能被修改了 (编译不通过)
    // fun consumer(itme: T)  /*{  消费代码  }*/

    // 只能被读取
    fun producer() : T
}

// 消费者 in T  逆变 [in T 此泛型只能被修改 更新 所以是in]
interface Consumer <in T> {
    // out T  代表整个生产者类里面  这个T  只能被读取,不能被修改了

    // 只能被修改了
    fun consumer(itme : T) /*{  消费代码  }*/

    // 不能被读取 (编译不通过)
    // fun producer() : T
}

// 生产者&消费者 T  默认情况下,是不变
interface ProducerAndConsumer<T> {
    // 能被修改了
    fun consumer(itme : T) /*{  消费代码  }*/

    // 能被读取
    fun producer() : T
}

open class Animal // 动物
open class Humanity : Animal() // 人类
open class Man : Humanity() // 男人
open class WoMan : Humanity() // 女人

// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  只管生产者
class ProducerClass1 : Producer<Animal> {
    override fun producer(): Animal {
        println("生产者 Animal")
        return Animal()
    }
}

class ProducerClass2 : Producer<Humanity> {
    override fun producer(): Humanity {
        println("生产者 Humanity")
        return Humanity()
    }
}

class ProducerClass3 : Producer<Man> {
    override fun producer(): Man {
        println("生产者 Man")
        return Man()
    }
}

class ProducerClass4 : Producer<WoMan> {
    override fun producer(): WoMan {
        println("生产者 WoMan")
        return WoMan()
    }
}

fun main() {
    val p1 : Producer<Animal> = ProducerClass1() // ProducerClass1他本来就是 传递 Animal ,当然是可以的

    val p2 : Producer<Animal> = ProducerClass2() // ProducerClass2他本来就是 传递 Humanity,居然也可以,因为out
    val p3 : Producer<Animal> = ProducerClass3() // ProducerClass3他本来就是 传递 Man,居然也可以,因为out
    val p4 : Producer<Animal> = ProducerClass4() // ProducerClass4他本来就是 传递 WoMan,居然也可以,因为out

    // 泛型默认情况下是:泛型的子类对象 不可以赋值给 泛型的父类对象
    // out: 泛型的子类对象 可以赋值给 泛型的父类对象
    // ? extends T 就相当于 KT里面的out,所以才可以 泛型子类对象 赋值给 泛型父类对象
    //java中
    List<? extends CharSequence> list2 = new ArrayList<String>();//可以
    //         List<CharSequence> list1 = new ArrayList<String>();//报错
}


in-逆变


// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  只管消费者
class ConsumerClass1 : Consumer<Animal> {
    override fun consumer(item: Animal) {
        println("消费者 Animal")
    }
}

class ConsumerClass2 : Consumer<Humanity> {
    override fun consumer(item: Humanity) {
        println("消费者 Humanity")
    }
}

class ConsumerClass3 : Consumer<Man> {
    override fun consumer(item: Man) {
        println("消费者 Man")
    }
}

class ConsumerrClass4 : Consumer<WoMan> {
    override fun consumer(item: WoMan) {
        println("消费者 WoMan")
    }
}

fun main() {
    val p1 : Consumer<Man> = ConsumerClass1() // ConsumerClass1他本来就是 传递 Animal
    val p2 : Consumer<WoMan> = ConsumerClass2() // ConsumerClass1他本来就是 传递 Humanity,居然也可以,因为in

    // 默认情况下: 泛型具体出的父类  是不可以赋值给  泛型声明处的子类的
    // in:泛型具体出的父类  是可以赋值给  泛型声明处的子类的
    
    //JAVA中
    //List<String> list1 = new ArrayList<CharSequence>();//报错
     List<? super String> list2 = new ArrayList<CharSequence>();//可以
    // ? super T 就相当于 KT里面的in,所以才可以 泛型父类对象 赋值给 泛型子类对象
}

in和out的综合运用


// 整个 SetClass 里面的所有成员 泛型相关,只能修改 更改,
//                                    不能获取人家 读取人家的
// 小结:当我们 对这个整个类里面的泛型,只能修改 ,不能让外界读取时,可以声明 in T 逆变
class SetClass<in T>() {

    // 200个函数 这200个函数 对T只能修改,不能给外界读取
    // ...

    fun set1(item: T) {
        println("set1 你要设置的item是:$item")
    }

    fun set2(item: T) {
        println("set2 你要设置的item是:$item")
    }

    fun set3(item: T) {
        println("set3 你要设置的item是:$item")
    }

    // ...

    // 不能给外界读取 (增加in后,不能给外界读取,所以编译不通过)
    /*fun get1() : T? {
        return null
    }

    fun get2() : T? {
        return null
    }

    fun get3() : T? {
        return null
    }*/

    // ...
}


// 整个 GetClass 里面的所有成员 泛型相关,不能修改 更改,
//                                    只能获取人家 读取人家的
// 小结:当我们 对这个整个类里面的泛型,只能给读取 ,不能修改 更改,可以声明 out T 协变
class GetClass<out T>(_item: T) {

    val item: T = _item

    // 200个函数 这200个函数 对T只能读取,不能给外界修改 更改
    // ...

    // 不能给外界修改 更改 (增加out后,不能给外界修改 更改,所以编译不通过)
    /*fun set1(item : T) {
        println("set1 你要设置的item是:$item")
    }

    fun set2(item : T) {
        println("set2 你要设置的item是:$item")
    }

    fun set3(item : T) {
        println("set3 你要设置的item是:$item")
    }*/

    // ...


    fun get1(): T {
        return item
    }

    fun get2(): T {
        return item
    }

    fun get3(): T? {
        return item
    }

    // ...
}

fun main() {
    // 逆变 in T  SetClass 只能修改 更改 不能给外界读取
    val p1 = SetClass<String>()
    p1.set1("Derry")
    p1.set2("Kevin")

    println()

    // 协变 out T GetClass 只能读取,不能修改 更改
    val p2 = GetClass("李四")
    println(p2.get1())
    val p3 = GetClass("王五")
    println(p3.get3())
}

reified关键字

//如果is关键字作用域泛型,则必须在方法中添加reified关键字,并且必须是inline函数
//reified 关键字使用就可以在泛型函数中获取到反射类型的Class对象
inline fun<reified T> randomOrDefault() :T? {
        val objList : List<Any> = listOf(ObjectClass1("obj1 李四", 22, "学习C"),
            ObjectClass2("obj2 王五", 23, "学习C++"),
            ObjectClass3("obj3 赵六", 24, "学习C#"))

        val randomObj : Any? = objList.shuffled().first()

        println("您随机产生的对象 幸运儿是:$randomObj")
        return randomObj.takeIf { it is T } as T?  
    }

定义扩展函数

导入扩展文件 在工作中非常有用,可以把很多的扩展操作,写到某一个地方,到时候引入过来用,比较独立化。

class Test (val name: String, val age: Int, val sex: Char)

// 增加扩展函数
fun Test.show() {
    println("我是show函数, name:${name}, age:$age, sex:$sex")
}

// 增加扩展函数
fun Test.getInfo() = "我是getInfo函数, name:${name}, age:$age, sex:$sex"

fun String.addExtAction(number: Int) =  this + "@".repeat(number)

fun String.showStr() = println(this)

/* 增加扩展函数后 的 背后代码

    public final class Test {

        public static final void show(Test $this$show) {
            System.out.println("我是show函数, name:" + $this$show.name + ", age:" + $this$show.age, sex:" + $this$show.sex);
        }

        public static final void getInfo(Test $this$getInfo) {
            return "我是getInfo函数, name:" + $this$show.name + ", age:" + $this$show.age, sex:" + $this$show.sex;
        }

        public static final void showStr(String $this$showStr) {
            System.out.println($this$showStr);
        }

        public static final String addExtAction(String $this$addExtAction) {
           return $this$addExtAction + StringsKt.repeat((CharSequence)"@", number);
        }

        public static void main(String [] args) {
            main();
        }

        public static void main() {
            // ...
        }
    }
 */

// Test.xxx  xxx函数里面会持有this == Test对象本身
fun main() {
    val p = Test("张三", 28, '男')
    p.show()
    println(p.getInfo())

    println("Derry".addExtAction(8))
    println("Kevin".addExtAction(3))

    "这个是我的日志信息".showStr()
    "Beyond".showStr()
}

//还可以对超类进行扩展,这样所有的子类都可以用
fun Any.showPrintlnContent() = println("当前内容是:$this")

//注意:
// 第一点:如果我们自己写了两个一样的扩展函数,编译不通过
// 第二点:KT内置的扩展函数,被我们重复定义,属于覆盖,而且优先使用我们自己定义的扩展函数
public fun File.readLines(charset: Charset = Charsets.UTF_8): List<String> {
    val result = ArrayList<String>()
    forEachLine(charset) { result.add(it); }
    return result
}

/*output:
我是show函数, name:张三, age:28, sex:男
我是getInfo函数, name:张三, age:28, sex:男
Derry@@@@@@@@
Kevin@@@
这个是我的日志信息
Beyond
*/

扩展属性

// 你必须把前面的普通方式学会:
val myStr : String = "AAA"
/* 背后代码:
   public final class KtBase117Kt {

       @NotNull
       private static final String myStr = "AAA";

       @NotNull
       public static final String getMyStr() {
            return myStr;
       }
   }
 */

// 扩展属性:只能是val,无法定义var
val String.myInfo: String
    get() = "Derry"
   // set(value)="123" 无法使用

/* 背后代码:

   public final class KtBase117Kt {

       真实情况:
       @NotNull
       public static final String getMyInfo(@NotNull String $this$myInfo) {
          Intrinsics.checkParameterIsNotNull($this$myInfo, "$this$myInfo");
          return "Derry";
       }
   }

 */

// 打印输出 并且 链式调用 (只有String有资格这样)
fun String.showPrintln() : String {
    println("打印输出 并且 链式调用 (只有String有资格这样):内容$this")
    return this
}

val String.stringAllInfoValueVal
    get() = "当前${System.currentTimeMillis()}这个时间点被调用了一次,当前的值是:$this,当前字符串长度是:$length"

fun main() {
    val str : String = "ABC"
    println(str.myInfo)

    str.showPrintln().showPrintln().showPrintln().showPrintln()

    str.myInfo.showPrintln().showPrintln().showPrintln()

    "Derry".stringAllInfoValueVal // 扩展属性
        .showPrintln().showPrintln().showPrintln().showPrintln() // 扩展函数

}

泛型扩展函数

fun main() {
    val r: Char = "Derry".mLet {
        it
        true
        "OK"
        'A'
    }

    123.mLet {
        it
    }

    'C'.mLet {
        it
    }

    // 万能类型,任何类型,所有类型,都可以使用我的 mLet
    val r2 : String = "Derry2".let {
        it
        34543.45f
        "Derry"
    }
}
// I.mLet 对I输入Input进行函数扩展,扩展函数的名称是 mLet,意味着,所有的类型,万能类型,都可以用 xxx.mLet
// lambda : (I) -> O   (I输入参数) -> O输出
//  : O  会根据用户的返回类型,变化而变化
// lambda(this) I进行函数扩展,在整个扩展函数里面,this == I本身
private inline fun<I, O> I.mLet(lambda : (I) -> O) : O = lambda(this)

可空类型扩展函数


// 对 String?==可空类型的 进行函数扩展,并且有备用值
fun String?.outputStringValueFun(defalutValue : String) = println(this ?: defalutValue)

// 编译期非常智能:能够监测到你做了if判断(能够对你代码逻辑监测),就知道后续类型
fun String?.outputStringValueFunGet(defaultValue : String) = this ?: defaultValue

// TODO 118-Kotlin语言的可空类型扩展函数
// 如果是null,就输出默认值
fun main() {
    val infoValue : String ? = null // infoValue是可空的类型  String  String?==可空类型的
    infoValue.outputStringValueFun("我是默认值啊1")
    val name = "Derry"
    name.outputStringValueFun("我是默认值啊2")

    // >>>>>>>>>>>>>>
    println(infoValue.outputStringValueFunGet("我是默认值啊3"))
    println(name.outputStringValueFunGet("我是默认值啊4"))
}

infix关键字

// 自定义的中缀表达式 + 扩展函数 一起用的     使用者: "一".gogogo(1)  "一" gogogo 1
// 1.条件一  对第一个参数 C1.gogogo  函数扩展
// 2.条件二  需要在 括号(c2: C2) 参数里面,传递一个参数
private infix fun <C1, C2> C1.gogogo(c2: C2) {
    // 做很多的逻辑
    // ...
    // 省略几万行代码
    println("我们的中缀表达式,对一个参数的内容是:$this")
    println("我们的中缀表达式,对二个参数的内容是:$c2")
}
// infix == 中缀表达式 可以简化我的代码
fun main() {
    // 下面是我们map自带的中缀表达式
    mapOf("零".to(0))

    mapOf("一" to 1)
    mapOf("二" to 2)
    mapOf("三" to 3)

    // 下面是我们自己写的中缀表达式
    123 gogogo '男'
    "Derry".gogogo('M')
    "Derry2" gogogo 'M'
}

map变换函数

fun main() {
    val list = listOf("李元霸", "李连杰", "李小龙")
    // T T T  --->  新的集合(R, R, R)
    // 原理:就是把你 匿名函数 最后一行的返回值 加入一个新的集合,新集合的泛型是R,并且返回新集合
    val list2 : List<Int> = list.map {
        // it = T == 元素 == String
        "【$it】"
        88
    }
    println(list2)

    // 用途: 和 RxJava的思路,一模一样
    val list3 : List<String> = list.map {
        "姓名是:$it"
    }.map {
        "$it,文字的长度是:${it.length}"
    }.map {
        "【$it】"
    }
    for (s in list3) {
        print("$s  ")
    }

    println()

    list.map {
        "姓名是:$it"
    }.map {
        "$it,文字的长度是:${it.length}"
    }.map {
        "【$it】"
    }.map {
        print("$it  ")
    }
}

//output:
//[88, 88, 88]
//【姓名是:李元霸,文字的长度是:7】  【姓名是:李连杰,文字的长度是:7】  【姓名是:李小龙,文字的长度是:7】  
//【姓名是:李元霸,文字的长度是:7】  【姓名是:李连杰,文字的长度是:7】  【姓名是:李小龙,文字的长度是:7】 

filter过滤函数

fun main() {
    // println("126-Kotlin语言的过滤函数-filter")

    val nameLists = listOf(
        listOf("黄晓明", "李连杰", "李小龙"),
        listOf("刘军", "李元霸", "刘明"),
        listOf("刘俊", "黄家驹", "黄飞鸿")
    )

    nameLists.map {
        // it ==  nameLists的元素 == listOf("黄晓明", "李连杰", "李小龙"),
        println(it)
    }

    println()

    nameLists.flatMap {
        // it ==  nameLists的元素 == listOf("黄晓明", "李连杰", "李小龙"),
        println(it)

        listOf("")//flatmap一定要返回一个集合
    }

    println()

    nameLists.map {
            it -> it.filter {
        true
    }
    }.map {
        print("$it   ")
    }

    println()
    println()

    nameLists.flatMap {
            it -> it.filter {
        true
    }
    }.map {
        print("$it   ")
    }

    println()
    println()

    // List<T> 返回给 map 后的效果: [黄晓明, 李连杰, 李小龙]   [刘军, 李元霸, 刘明]   [刘俊, 黄家驹, 黄飞鸿]
    // List<T> 返回给 flatMap 效果: 黄晓明   李连杰   李小龙   刘军   李元霸   刘明   刘俊   黄家驹   黄飞鸿

    nameLists.flatMap {
            it -> it.filter {
        it.contains('黄') // 包含 ‘黄’ true,否则是false
    }
    }.map {
        print("$it   ")
    }

}

//output:
/*[黄晓明, 李连杰, 李小龙]
[刘军, 李元霸, 刘明]
[刘俊, 黄家驹, 黄飞鸿]

[黄晓明, 李连杰, 李小龙]
[刘军, 李元霸, 刘明]
[刘俊, 黄家驹, 黄飞鸿]

[黄晓明, 李连杰, 李小龙]   [刘军, 李元霸, 刘明]   [刘俊, 黄家驹, 黄飞鸿]   

黄晓明   李连杰   李小龙   刘军   李元霸   刘明   刘俊   黄家驹   黄飞鸿   

黄晓明   黄家驹   黄飞鸿   */

flatMap变换函数

// map {返回类型:T String Int Boolean Char ...  是把每一个元素(String)加入到新集合,最后返回新集合 List<String>}
// flatMap {返回类型:每一个元素 T 集合1 集合2 集合3 ... 是把每一个元素(集合)加入到新集合,最后返回新集合 List<List<String>> 最终内部会处理成List<String>}

// TODO flatMap 相当于 List<List<String>> 集合的集合,有嵌套关系

fun main() {
    val list : List<String> = listOf("李四", "王五", "赵六", "初七")

    val newList : List<String> = list.map {
        "你的姓名是:$it" // 每次返回一个 String
    }.map {
        "$it, 你文字的长度是:${it.length}" // 每次返回一个 String
    }.flatMap {
        listOf("$it 在学习C++", "$it 在学习Java", "$it 在学习Kotlin") // 每次返回一个集合,四次
    }
    println(newList)

    println()

    /*
    [你的姓名是:李四, 你文字的长度是:8 在学习C++,
     你的姓名是:李四, 你文字的长度是:8 在学习Java,
     你的姓名是:李四, 你文字的长度是:8 在学习Kotlin,

     你的姓名是:王五, 你文字的长度是:8 在学习C++,
     你的姓名是:王五, 你文字的长度是:8 在学习Java,
     你的姓名是:王五, 你文字的长度是:8 在学习Kotlin,

     你的姓名是:赵六, 你文字的长度是:8 在学习C++,
     你的姓名是:赵六, 你文字的长度是:8 在学习Java,
     你的姓名是:赵六, 你文字的长度是:8 在学习Kotlin,

     你的姓名是:初七, 你文字的长度是:8 在学习C++,
     你的姓名是:初七, 你文字的长度是:8 在学习Java,
     你的姓名是:初七, 你文字的长度是:8 在学习Kotlin]
     */

    // 原理:就是把你 匿名函数 最后一行的返回值(又是一个集合listOf(......)) 加入一个新的集合,新集合的泛型是R,并且返回新集合
}

kotlin与java互操作性与可空性

public class KtBase129 {

    public String getInfo1() {
        return "Derry Info1";
    }

    public String getInfo2() {
        return null;
    }
}

fun main() {
    // 下面是 Java 与 KT 交互 ,错误的案例
    println(KtBase129().info1.length)
    // println(KtBase129().info2.length) // 引发空指针异常

    // 下面是 Java 与 KT 交互 ,错误的案例
    // : String! Java 与 KT 交互的时候,Java给KT用的值,都是 : String! 这种类型
    val info1  = KtBase129().info1
    val info2 = KtBase129().info2
    println(info1.length)
    // println(info2.length) // 引发空指针异常


    // 下面是 Java 与 KT 交互 ,正确的案例1
    // : String! Java 与 KT 交互的时候,Java给KT用的值,都是 : String! 这种类型
    // 只要是看到有  String! 的类型,在使用的时候,必须 ?.xxx,这个是规则1 这个规则1不好,如果忘记写,就有风险
    val info1s  = KtBase129().info1
    val info2s = KtBase129().info2
    println(info1s?.length)
    println(info2s?.length)

    // 下面是 Java 与 KT 交互 ,正确的案例2 (推荐)
    // : String! Java 与 KT 交互的时候,Java给KT用的值,都是 : String! 这种类型
    // 只要是看到有  String! 的类型,在使用的时候,必须 : String? 来接收Java值,这个是规则2(直接限定你不会出错了)
    val info1ss : String?  = KtBase129().info1
    val info2ss : String? = KtBase129().info2
    println(info1ss?.length)
    println(info2ss?.length)
}

合并函数-zip

fun main() {
    val names = listOf("张三", "李四", "王五")
    val ages = listOf(20, 21, 22)

    // RxJava zip 合并操作符
    // KT 自带就有zip 合并操作

    // 原理:就是把 第一个集合 和 第二个集合 合并起来,创建新的集合,并返回
    //      创建新的集合(元素,元素,元素) 元素Pair(K, V)  K代替第一个集合的元素   V代替第二个集合的元素
    val zip : List<Pair<String, Int>> = names.zip(ages)
    println(zip)
    println(zip.toMap())
    println(zip.toMutableSet())
    println(zip.toMutableList())

    println()

    // 遍历
    zip.forEach {
        // it == Pair<String, Int>
        println("姓名是:${it.first}, 年龄是:${it.second}")
    }

    println()

    // map 普通方式
    zip.toMap().forEach { k, v ->
        println("姓名是:${k}, 年龄是:${v}")
    }

    println()

    // map 解构的方式
    zip.toMap().forEach { (k, v) ->
        println("姓名是:${k}, 年龄是:${v}")
    }

    println()

    zip.toMap().forEach {
        // it == Map的元素 每一个元素 有K和V,  Map.Entry<String, Int>
        // it == Pair<String, Int>
        println("姓名是:${it.key}, 年龄是:${it.value}")
    }
}

接口定义与默认实现

// 1.接口里面的所有成员 和 接口本身 都是 public open 的,所以不需要open,这个是接口的特殊
// 2.接口不能有主构造,反正就是没有构造
// 3.实现类不仅仅要重写接口的函数,也要重写 接口的成员变量
// 4.接口实现代码区域,全部都要增加 override 关键字来修饰

interface IUSB {
    val usbVersionInfo: String // USB版本相关的信息
    get() = "IUSB"//如果给接口成员赋予默认实现,必须是val修饰,但是一般不建议接口加入默认实现

    var usbInsertDevice: String // USB插入的设备信息

    fun insertUBS() : String
	fun insertUBS2() : String{//默认实现
        return ""
    }
}

class Mouse : IUSB{
    override var usbVersionInfo: String ="MouseInfo"
    override var usbInsertDevice: String = "MouseDevice"

    override fun insertUBS(): String {
        return "Mouse ${usbVersionInfo} ,${usbInsertDevice}"
    }

}

//这种实现接口的方式与上面的效果一样
class Mouse2(override var usbVersionInfo: String, override var usbInsertDevice: String) : IUSB{
    override fun insertUBS(): String {
        return "Mouse ${usbVersionInfo} ,${usbInsertDevice}"
    }

}

class Mouse1 : IUSB{
    override var usbInsertDevice: String=""

    override fun insertUBS(): String {
        return "Mouse ${usbVersionInfo} ,${usbInsertDevice}"
    }

}

fun main() {
    var mouse = Mouse()
    println(mouse.insertUBS())
    var mouse1 = Mouse1()
    println(mouse1.insertUBS())
}

注解@JvmName

//Kt文件
@file:JvmName("Stu") // 就是在编译器环节,修改我们的类的名字,让Java端调用更简洁

package aaa.test

// @file:JvmName("Stu") 注意:必须写在 包名的外面

fun getStudentNameValueInfo(str : String) = println(str)

fun main() {}

/* 背后生成的代码:

    public final class TestKt {

        public static final void getStudentNameValueInfo(@NotNull String str) {
            System.out.println(str);
        }

        public static final void main() {
        }

        public static void main(String[] args) {
            main();
        }
    }


    @file:JvmName("Stu") 背后的原理
    public final class Stu {

        public static final void getStudentNameValueInfo(@NotNull String str) {
            System.out.println(str);
        }

        public static final void main() {
        }

        public static void main(String[] args) {
            main();
        }
    }
 */
//=====================
//java文件
//import aaa.test.Stu;
import aaa.test.TestKt;

public class test {

    public static void main(String[] args) {
//        Stu.getStudentNameValueInfo("aaaaa");
        TestKt.getStudentNameValueInfo("aaaa");
    }
}

注解@JvmField

class Person {
    @JvmField
    val names = listOf("Zhangsan", "Lisi", "Wangwu")
}

/* 背后的原理代码:

    public final class Person{

        @NotNull
        private final List names = CollectionsKt.listOf(new String[]{"Zhangsan", "Lisi", "Wangwu"});

        // val 只读的,只有 getNames
        public final List getNames() {
            return this.names;
        }
    }
    @JvmField 背后会剔除私有代码 成员
    public final class Person {
       @JvmField
       @NotNull
       public final List names = CollectionsKt.listOf(new String[]{"Zhangsan", "Lisi", "Wangwu"});
    }
 */


public class test {

    public static void main(String[] args) {
        Person person = new Person();
        for (String name : person.names) {
            System.out.println(name);
        }
    }
}

注解@JvmOverloads

// 默认参数
fun show( name : String, age : Int = 20, sex : Char = 'M') {
    println("name:$name, age:$age, sex:$sex")
}

// 默认参数
@JvmOverloads // 原理:编译器环节 专门重载一个函数,专门给 Java用
fun toast( name : String, sex : Char = 'M') {
    println("name:$name, sex:$sex")
}
fun main() {
    // KT端
    show("张三")
    toast("李四")
}

public class test {

    public static void main(String[] args) {
        // Java端
        // TestKt.show("张三") // Java无法享用 KT的默认参数

        TestKt.toast("张三"); // 相当于 Java 享用 KT的默认参数
    }
}

注解@JvmStatic

class MyObject {

    companion object {

        @JvmField
        val TARGET = "黄石公园"

        @JvmStatic
        fun showAction(name: String) = println("$name 要去 $TARGET 玩")
    }
}

fun main() {
    // KT 端
    MyObject.TARGET

    MyObject.showAction("Derry")
}

public class test {

    public static void main(String[] args) {
        // Java 端
        System.out.println(MyObject.TARGET);

        MyObject.showAction("Kevin");
    }
}

注意

使用kotlin改造java项目的时候,特别注意方法中参数的类型需要加“?“,因为如果是Java方法调用kotlin方法,参数是null的话会崩溃。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值