Android开发,Kotlin的了解与学习(八)-----kotlin与java的互相调用
2017-06-22 14:23
781 查看
本来呢,这一章是想开始kotlin在android中的用法了,后来发现,还有一个东西没有提到,那就是kotlin与java的互相代用。之前提到过java与kotlin是可以相互调用的,估计很多人就去尝试在kotlin的kt文件中,调用java的一些方法,发现还是有一些东西需要学的。
上面的Calendar就是java中的代码了
这一段,是官方的,但是估计直接看不是很能明白他的get、set的意思,我们换一种方式,如下:
可以看到我们的实体类里面有一个参数,name,我们并没有设置他的set和get方法
但是在bookDemo这个方法中,我们不仅调用了book.name的值,还给他重新赋值了,也就是调用了set和get的方法。
另外,如果像这样:
我们手动添加一个set方法,你会发现,会出错的。
Platform decalration clash: The following declarations have the same JVM signature
平台声明冲突:以下声明具有相同的JVM签名
就是说,我们已经有这个方法了,请不要再次创建相同的方法
同样的
get也是不允许的
那么我们换一种,创建一个java的实体类
我们可以发现,仍然可以使用book.name进行赋值和获取,那么如果像这样呢
你会发现
如上,我们不仅可以调用kotlin的book.name = "....",也可以调用java的book.getName()
我们可以看到is被一对单引号包裹起来了,事实上,我们写的时候也不需要主动去写这个单引号,因为在使用的时候,他会自动的加上的。
那么,在kotlin中调用时,
是不会像kotlin本身代码那样在编译之前就报错的,而是会在代码运行之后再抛出exception。 Java 声明的类型在 Kotlin 中会被特别对待并称为平台类型。对这种类型的空检查会放宽, 因此它们的安全保证与在 Java 中相同(这是官方原文)
平台类型是不可标示的,意味着不能在语言中明确地写下它们。 当把一个平台值赋值给一个 Kotlin 变量时,可以依赖类型推断(该变量会具有推断出的的平台类型, 如上例中 item 所具有的类型),或者我们可以选择我们期望的类型(可空或非空类型均可)
什么意思呢?意思就是,在我我们开发者明确知道,该类型是平台类型的时候,如果要进行赋值,不能像上面那样,直接赋值,而是需要这样:
在定义时就告诉系统我这个参数不安全,可能为空。
kotlin中使用java其实还有很多的东西需要了解,需要知道的可以去上面提供的地址查看,我这边不写了,因为其他的东西我觉得我们现在不需要急于去知道,知道太多反而容易乱。
如上,可以看到,在java代码中,先实例化一个Book类,然后在调用get和set的时候,我们可以直接调用set和get方法,而这两个方法,在Book类中是没有显示出来的。
如果需要在 Java 中将 Kotlin 属性作为字段暴露,那就需要使用 @JvmField 注解对其标注。
或者这样
再或者这样
这三种里面,多了三个我们暂时都没有看到过的修饰符。首先是laternit,这个代表的是延迟初始化。大体可以相当于这样:
代表着,我现在还没办法给这个参数赋值,我准备待会再进行赋值。
然后就是const了,其实const的意思很简单,就是说我这个参数不需要编译,值就已经定下来了,大概可以理解为
证明如下:
companion,这个是伴生类的意思,我的理解,就是专门用来充当static类型的综合类的,一个类的所有static类型都可以全部放在这个伴生类里面,具体的可能会出现不同,等待你们明白的提出来了。
class Book {
companion object{
@JvmStatic
fun bookFoo(){
}
}
}
上面两种调用方式都可以
private 成员编译成 private 成员;
private 的顶层声明编译成包级局部声明;
protected 保持 protected(注意 Java 允许访问同一个包中其他类的受保护成员, 而 Kotlin 不能,所以 Java 类会访问更广泛的代码);
internal 声明会成为 Java 中的 public。internal 类的成员会通过名字修饰,使其更难以在 Java 中意外使用到,并且根据 Kotlin 规则使其允许重载相同签名的成员而互不可见;
public 保持 public。
btn_interface.setOnClickListener {
var intent = Intent()
intent.setClass(this, MainActivity::class.java)
startActivity(intent)
}
注意里面的MainActivity :: class.java,这个方式,不仅仅是kotlin跳转到kotlin中,也可以是kotlin跳转到java中去。
但是java跳转到kotlin中,和java跳转到java中是一样的
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
这样是可以的。
kotlin中使用jiava
Kotlin的官方中文文档中其实也写到过,官方中文文档import java.util.* fun demo(source: List<Int>) { val list = ArrayList<Int>() // “for”-循环用于 Java 集合: for (item in source) { list.add(item) } // 操作符约定同样有效: for (i in 0..source.size() - 1) { list[i] = source[i] // 调用 get 和 set } }如上,
Getter和Setter
import java.util.Calendar fun calendarDemo() { val calendar = Calendar.getInstance() if (calendar.firstDayOfWeek == Calendar.SUNDAY) { // 调用 getFirstDayOfWeek() calendar.firstDayOfWeek = Calendar.MONDAY // 调用 setFirstDayOfWeek() } }
上面的Calendar就是java中的代码了
这一段,是官方的,但是估计直接看不是很能明白他的get、set的意思,我们换一种方式,如下:
fun bookDemo() { val book = Book() if ("my book".equals(book.name)) { // 调用 getBook() book.name = "your book" // 调用 setBook() } } class Book{ var name = "my book" }
可以看到我们的实体类里面有一个参数,name,我们并没有设置他的set和get方法
但是在bookDemo这个方法中,我们不仅调用了book.name的值,还给他重新赋值了,也就是调用了set和get的方法。
另外,如果像这样:
class Book { var name = "my book" fun setName(value: String) { name = value } }
我们手动添加一个set方法,你会发现,会出错的。
Platform decalration clash: The following declarations have the same JVM signature
平台声明冲突:以下声明具有相同的JVM签名
就是说,我们已经有这个方法了,请不要再次创建相同的方法
同样的
class Book { var name = "my book" fun getName() : String{ return name } }
get也是不允许的
那么我们换一种,创建一个java的实体类
public class Books { public String name = "my book"; }
我们可以发现,仍然可以使用book.name进行赋值和获取,那么如果像这样呢
public class Books { public String name = "my book"; public String getName() { return name; } public void setName(String name) { this.name = name; } }
你会发现
fun bookDemo() { val book = Books() if ("my book".equals(book.getName())) { // 调用 getBook() book.name = "your book" // 调用 setBook() } }
如上,我们不仅可以调用kotlin的book.name = "....",也可以调用java的book.getName()
kotlin和java语法冲突的处理方式
我们知道,java中是不存在is、in等操作符的,在java中,可以这样设置一个方法名,就叫is(),那么如我们要在kotlin文件中,调用java的方法,遇到is怎么办呢?public boolean is() { return name.length() > 0; }
fun bookDemo() { val book = Books() if (book.`is`()) { // 调用 getBook() book.name = "your book" // 调用 setBook() } }
我们可以看到is被一对单引号包裹起来了,事实上,我们写的时候也不需要主动去写这个单引号,因为在使用的时候,他会自动的加上的。
kotlin对java中的空的处理
一直提到,kotlin是空指针安全的,但是java并不是,java可以定一个不赋值的参数,如下int num;
那么,在kotlin中调用时,
var a = book.num
是不会像kotlin本身代码那样在编译之前就报错的,而是会在代码运行之后再抛出exception。 Java 声明的类型在 Kotlin 中会被特别对待并称为平台类型。对这种类型的空检查会放宽, 因此它们的安全保证与在 Java 中相同(这是官方原文)
平台类型是不可标示的,意味着不能在语言中明确地写下它们。 当把一个平台值赋值给一个 Kotlin 变量时,可以依赖类型推断(该变量会具有推断出的的平台类型, 如上例中 item 所具有的类型),或者我们可以选择我们期望的类型(可空或非空类型均可)
什么意思呢?意思就是,在我我们开发者明确知道,该类型是平台类型的时候,如果要进行赋值,不能像上面那样,直接赋值,而是需要这样:
var a : Int? = book.num
在定义时就告诉系统我这个参数不安全,可能为空。
平台类型表示法
平台类型在kotlin中是无法准确的显示是否为空,是否存在等,所以在kotlin 中给这样的平台类型提供了一个符号!-----T! 表示“T 或者 T?”, -----(Mutable)Collection<T>! 表示“可以可变或不可变、可空或不可空的 T 的 Java 集合”, -----Array<(out) T>! 表示“可空或者不可空的 T(或 T 的子类型)的 Java 数组”
kotlin中使用java其实还有很多的东西需要了解,需要知道的可以去上面提供的地址查看,我这边不写了,因为其他的东西我觉得我们现在不需要急于去知道,知道太多反而容易乱。
java中使用kotlin
首先还是来看我们熟悉的getter和setter
class Book { var name = "my book" }
public void test(){ MainActivity.Book book = new MainActivity.Book(); book.getName(); }
如上,可以看到,在java代码中,先实例化一个Book类,然后在调用get和set的时候,我们可以直接调用set和get方法,而这两个方法,在Book类中是没有显示出来的。
实例字段
在上面的例子中,我们可以采用book.getName(),来获取到book这个字段,但是我们无法通过book.name直接得到这个参数。如果需要在 Java 中将 Kotlin 属性作为字段暴露,那就需要使用 @JvmField 注解对其标注。
class Book { @JvmField var name = "my book" }
public void test() { MainActivity.Book book = new MainActivity.Book(); String a = book.name; }
静态字段
我们知道,kotlin中没有static这个修饰符,那么我们在java中想要想平时那样,直接调用某个类中的static字段,而不需要new该怎么做呢。如下:class Book { companion object{ @JvmField var age = 10 } }
public void test() { MainActivity.Book.age }
或者这样
object ConstClass{ const val name : String = "5" }
public void test() { String name = MainActivity.ConstClass.name; }
再或者这样
object LaClass{ lateinit var sex : String }
public void test() { String sex = MainActivity.LaClass.sex; }
这三种里面,多了三个我们暂时都没有看到过的修饰符。首先是laternit,这个代表的是延迟初始化。大体可以相当于这样:
var sex :String = null
代表着,我现在还没办法给这个参数赋值,我准备待会再进行赋值。
然后就是const了,其实const的意思很简单,就是说我这个参数不需要编译,值就已经定下来了,大概可以理解为
public staic final ....
证明如下:
object LaClass{ lateinit var sex : String } object ConstClass{ const val name : String = "5" }
public void test() { MainActivity.LaClass.sex = "3";//这一句没有问题,可以通过 MainActivity.ConstClass.name = "6";//这一句是有问题的,不允许 }
companion,这个是伴生类的意思,我的理解,就是专门用来充当static类型的综合类的,一个类的所有static类型都可以全部放在这个伴生类里面,具体的可能会出现不同,等待你们明白的提出来了。
静态方法
静态方法的使用方法和静态字段差不多,如下class Book {
companion object{
@JvmStatic
fun bookFoo(){
}
}
}
public void test() { MainActivity.Book.bookFoo(); MainActivity.Book.Companion.bookFoo(); }
上面两种调用方式都可以
可见性
kotlin的可见性与java的可见性映射如下:private 成员编译成 private 成员;
private 的顶层声明编译成包级局部声明;
protected 保持 protected(注意 Java 允许访问同一个包中其他类的受保护成员, 而 Kotlin 不能,所以 Java 类会访问更广泛的代码);
internal 声明会成为 Java 中的 public。internal 类的成员会通过名字修饰,使其更难以在 Java 中意外使用到,并且根据 Kotlin 规则使其允许重载相同签名的成员而互不可见;
public 保持 public。
KClass转Class
有些人可能尝试过了,从kotlin跳转到java中去,发现不行,跳转方法其实有变化的,如下:btn_interface.setOnClickListener {
var intent = Intent()
intent.setClass(this, MainActivity::class.java)
startActivity(intent)
}
注意里面的MainActivity :: class.java,这个方式,不仅仅是kotlin跳转到kotlin中,也可以是kotlin跳转到java中去。
但是java跳转到kotlin中,和java跳转到java中是一样的
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
这样是可以的。
相关文章推荐
- Kotlin的了解与学习------kotlin与java的互相调用
- Android开发学习之路--Java和Js互相调用
- Android开发学习之路--Java和Js互相调用
- Android开发,Kotlin的了解与学习(一)-----下载与安装
- Android开发,Kotlin的了解与学习(五)-----基本语法之集合相关
- Android开发,Kotlin的了解与学习(二)-----Kotlin数据类型与Extensions的学习
- Android学习开发4--Android在C++中调用java
- Android开发,WebView下Java和JavaScript互相调用(2)
- Android开发,Kotlin的了解与学习(九)-----在Android上的具体应用
- Android开发,Kotlin的了解与学习(六)-----类与继承
- Android开发,Kotlin的了解与学习(七)-----接口与实现
- Android开发,Kotlin的了解与学习(三)-----流程控制语句
- kotlin开发Android入门篇七Kotlin与Java相互调用
- Android开发,Kotlin的了解与学习(四)-----基本语法之方法、操作符
- Android(java)学习笔记221:开发一个多界面的应用程序之不同界面间互相传递数据(短信助手案例)
- 【学习Android NDK开发】Java通过JNI调用native方法
- Android(java)学习笔记222:开发一个多界面的应用程序之不同界面间互相传递数据(短信助手案例的优化:请求码和结果码)
- android中实现JavaScript与Java之间实现互相调用
- 【学习Android遇到的错误】Android 开发遇到 java.lang.NoClassDefFoundError 错误
- Android-NDK开发之第四个例子--用C/C++调用Java