本文将Kotlin的使用与java相互对比,适合有java基础的人群观看
Kotlin每句末尾的分号可省略
1.定义变量、常量
Kotlin | Java | |
变量 | var string: String = "Hello" | String string = "Hello"; |
编译期常量 | const val string: String = "Hello" | final String string = "Hello"; |
非编译期常量 | val string: String = getString() | final String string = getString(); |
其中,Kotlin声明变量时可以自动推测字段类型,所以上文定义时也可以省略类型String。
如:
var quantity = 5
默认会被认为是int类型,如果你希望它是一个Double类型,则需要显示声明类型,如下:
var quantity: Double = 5
简单地说:用var声明变量,用val声明常量
2.定义函数
Kotlin | Java | |
有返回值 |
fun testString(name: String): Boolean {
...
}
|
public boolean testString(String name){
...
}
|
无返回值 |
fun testString(name: String) {
...
}
|
public void testString(String name){
...
}
|
可变参数 |
fun hasEmpty(vararg strArray: String?): Boolean{
for (str in strArray){
if ("".equals(str) || str == null)
return true
}
return false
}
|
public boolean hasEmpty(String... strArray){
for (String str : strArray){
if ("".equals(str) || str == null)
return true;
}
return false;
}
|
未指定返回值时,会返回Unit,与Java中的void类似,但Unit是一个真正的对象
如果返回的结果可以使用一个表达式计算出来,你可以不使用括号而是使用等号:
fun add(x: Int,y: Int) : Int = x + y
在Kotlin中,使用关键字vararg来表示可变参数
函数的默认参数
fun say(str: String = "hello"): String = str
此时调用say(),会得到默认的字符串 "hello",也可以自己传入参数使用
拓展函数
给父类添加一个方法,这个方法将可以在所有子类中使用
fun Activity.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(this, message, duration).show()
}
这样,我们就可以在每一个Activity中直接使用toast()函数了。
静态函数
在Java中静态函数通过static关键字来表明
public class Singleton{
private static Singleton instance = ...;
public static Singleton getInstance(){
...
return instance;
}
}
在Kotlin中静态函数通过 @JvmStatic 注解来表明
class KotlinSingleton{
companion object{
private val kotlinSingleton = KotlinSingleton()
fun getInstance() = kotlinSingleton
}
}
Kotlin 可以有包级函数,因此我们可以不声明一个类来包装某函数
companion object
companion object {
}
companion关键字仅有这个用法,只能在类中使用,相当于java中的静态内部类,随着类的加载而加载
companion object中定义的成员,类似于Java的静态成员,因为Kotlin中没有static成员
3.定义数组
Kotlin | Java | |
创建时初始化元素 | val names: Array<String> = arrayOf("Kyo", "Ryu", "Iory") | String[] names = new String[]{"Kyo", "Ryu", "Iory"}; |
创建时不初始化元素(都为null) | val emptyStrings: Array<String?> = arrayOfNulls(10) | String[] emptyStrings = new String[10]; |
为了避免装箱和拆箱的开销,Kotlin 对基本类型包括 Int、Short、Byte、Long、Float、Double、Char 等基本类型提供了定制版数组类型,写法为 XArray,例如 Int 的定制版数组为 IntArray,如果我们要定义一个整型数组,写法如下:
val ints = intArrayOf(1, 3, 5)
4.三元运算符
Kotlin | Java |
int code = if(isSuccessfully) 200 else 400 | int code = isSuccessfully? 200: 400; |
在Kotlin中,if else 这样的语句是表达式,这一点与 Java 不同
5.定义类与创建对象
定义类
定义一个类只需要使用class关键字
class MainActivity{
}
它有一个默认唯一的构造器。在特殊的情况下我们可以创建其它额外的构造器,但大部分情况下你只需要这个默认的构造器。
你只需要在类名后面写上它的参数。如果这个类没有任何内容可以省略大括号:
class Person(name: String, surname: String)
构造函数的函数体可以写在init块中:
class Person(name: String, surname: String) {
init{
...
}
}
类继承
任何类都继承自Any类(类似于Java中的Object类)。
所有类默认不可被继承(final),只能继承那些明确声明open或者abstract的类:
open class Animal(name: String)
class Person(name: String, surname: String) : Animal(name)
当我们只有单个构造器时,我们需要在从父类继承下来的构造器中指定需要的参数。这是用来替换Java中的super调用的。
重写
如上文“类继承”所说,使用fun声明函数时,此函数默认使用final修饰,不能被子类重写。
如果允许子类重写该函数,就要使用open修饰它,子类重写该方法时使用override关键词
/**用户基类**/
open class Person{
open fun study(){ // 允许子类重写
println("我毕业了")
}
}
/**子类继承 Person 类**/
class Student : Person() {
override fun study(){ // 重写方法
println("我在读大学")
}
}
创建对象
不需要new
Kotlin | Java |
val date = Date() | Date date = new Date(); |
获取.class实例
Kotlin | Java | |
类 |
class Hello
|
public class Hello{
...
}
|
通过类名获取 | val clazz = Hello::class.java | Class<?> clazz = Hello.class; |
通过实例获取 |
val hello = Hello()
val clazz2 = hello.javaClass
|
Hello hello = new Hello();
Class<?> clazz2 = hello.getClass();
|
这里双冒号是起到了反射获取class实例的作用(双冒号还有其他作用
http://www.jianshu.com/p/2efe93c9abf4
)
格式: T::class.simpleName
6.空值检测
引用或函数返回值如果可能为null值,则
必须在其类型后面显式标记其可以为空:
问号表示可能为空。
就是说声明了问号之后,在使用它的时候,也必须声明问号。
比如:
var c: String? = null
在调用c的方法时,要这样写:
c?.length()
这样写的好处就是,如果c为空的时候,length()这个方法就不会调用。在很大程度上减少了空指针异常的发生。
两个叹号表示一定不为空。
如果你确定该成员一定不会为空时,可以在其类型后方声明两个叹号。这样Kotlin的编译器会认为后续的调用已经无需进行空值检测了。