泛型与类型约束
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的话会崩溃。