配置相关
在build.gradle(app)中添加的内容
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
apply plugin: 'kotlin-android-extensions'
其中第二个库的作用是解决findViewById()问题
The Kotlin Android Extensions plugin allows us to obtain the same experience we have with some of these libraries, without having to add any extra code or shipping any additional runtime.
简单创建项目流程
新建Activity并转换成Kotlin类
文档里提到的两点
- Skip the "Converting Java code to Kotlin" step in Android Studio 3.0(3.0以后可以直接生成)
- Write it in Java, then copy-paste it into Kotlin file, and IDE will suggest to convert it
convert的快捷键是先输入Ctrl+Shift+A
然后再在弹出的对话框中输入convert
或者直接按Ctrl+Shift+ALT+K
如果是第一次在项目中使用java转换kotlin,则需要config一下
语法
hello world
最简版
Java | Kotlin | |
---|---|---|
方法标志 | fun | |
数组标志 | [ ] | Array |
形参 | 形参类型+形参名 | 形参名:形参类型 |
句尾 | 分号 | 无 |
进化1:array access版
- args.size
- ${args[0]}
fun main(args: Array<String>) {
if (args.size == 0) {
println("Please provide a name as a command-line argument")
return
}
println("Hello, ${args[0]}!")
}
进化2: 循环版
for (name in args)
println("Hello, $name!")
进化3:分支版
- if(条件) 结果1 else 结果2
- when (条件){条件1->结果1...else->default结果 }
fun main(args: Array<String>) {
val language = if (args.size == 0) "EN" else args[0]
println(when (language) {
"EN" -> "Hello!"
"FR" -> "Salut!"
"IT" -> "Ciao!"
else -> "Sorry, I can't greet you in $language yet"
})
}
进化4:面向对象版
class Greeter(val name: String) {
fun greet() {
println("Hello, ${name}");
}
}
fun main(args: Array<String>) {
Greeter(args[0]).greet()
}
基本语法
条件表达式
搞一个性别转换器,把男的变成女的,女的变成男的
fun main(args: Array<String>) {
println(transSex(args[0]))
}
fun transSex(a: String) = if (a == "男") "女" else "男"
非空检查
Null Safety
以下一例是Kotlin的空值检查简单示例,计算两个值的乘积。分别对输入的两个值进行check,看是不是int,如果不是的话,catch异常,如果有一个输入为空的话,则在main方法中处理。
// Return null if str does not hold a number
fun parseInt(str: String): Int? {
try {
return str.toInt()
} catch (e: NumberFormatException) {
println("One of the arguments isn't Int")
}
return null
}
fun main(args: Array<String>) {
if (args.size < 2) {
println("No number supplied");
} else {
val x = parseInt(args[0])
val y = parseInt(args[1])
// We cannot say 'x * y' now because they may hold nulls
if (x != null && y != null) {
print(x * y) // Now we can
} else {
println("One of the arguments is null")
}
}
}
is检查
类似于java中的instanceOf方法,这样在调用is-checked type的obj的方法时就不用再强转。
Kotlin中的Any就是Java中的Object吗?
/**
* The `is` operator checks if an expression is an instance of a type and more.
* If we is-checked an immutable local variable or property, there's no need
* to cast it explicitly to the is-checked type.
* See this pages for details:
* http://kotlinlang.org/docs/reference/classes.html#classes-and-inheritance
* http://kotlinlang.org/docs/reference/typecasts.html#smart-casts
*/
fun main(args: Array<String>) {
println(getStringLength("aaa"))
println(getStringLength(1))
}
fun getStringLength(obj: Any): Int? {
if (obj is String)
return obj.length // no cast to String is needed
return null
}
此例中还出现了Int?,以下对此进行详细的讨论:
在Kotlin中,在reference分成了nullable references和non-null references,比方讲一个常规的String变量是不能赋null值的,如果强行赋值,则会报compilation error。
如果想不报编译错误的话,就在String后面加一个问号,使该string reference成为nullable string。
这时因为a可能为空值,如果去获取a的长度的话,则会报编译错误
解决方法是在.之前加上一个?。如果a不为null那么就返回a的长度,如果a为null就返回null。
还有一种方式就是在.之前加上!!,使用改操作符的区别是,如果a是null,抛出NPE。
如果在这一例的Int后面不加?的话,则编译不会通过,因为Int类不接受null值,Int?接收
循环语句
While
fun main(args: Array<String>) {
var i = 0
while (i < args.size)
println(args[i++])
}
For
fun main(args: Array<String>) {
for (arg in args)
println(arg)
// or
println()
for (i in args.indices)
println(args[i])
}
输入4及输出结果:
a..b相当于[a,b]
!in:不在
${x}:用在" "中
fun main(args: Array<String>) {
val x = args[0].toInt()
//Check if a number lies within a range:
val y = 10
if (x in 1..y - 1)
println("OK")
//Iterate over a range:
for (a in 1..5)
print("${a} ")
//Check if a number is out of range:
println()
val array = arrayListOf<String>()
array.add("aaa")
array.add("bbb")
array.add("ccc")
if (x !in 0..array.size - 1)
println("Out: array has only ${array.size} elements. x = ${x}")
//Check if a collection contains an object:
if ("aaa" in array) // collection.contains(obj) is called
println("Yes: array contains aaa")
if ("ddd" in array) // collection.contains(obj) is called
println("Yes: array contains ddd")
else
println("No: array doesn't contains ddd")
}
When
is和!is,类型检查
输出结果:
fun main(args: Array<String>) {
cases("Hello")
cases(1)
cases(0L)
cases(MyClass())
cases("hello")
}
fun cases(obj: Any) {
when (obj) {
1 -> println("One")
"Hello" -> println("Greeting")
is Long -> println("Long")
!is String -> println("Not a string")
else -> println("Unknown")
}
}
class MyClass() {
}
补充:
Java中的异常问题
Java异常的官方教程
Exception handling in Java?
Java中使用try...catch原因
What is the purpose of the try and catch blocks in Exceptions?
综上,使用try...catch第一个作用是避免大量if...else使用,在第一例中,file的引用可能为空,line的引用也可能为空。用if...else,就要先判断file不为空的情况,如果file不为空,再判断str不为空的情况。用try...catch则把整个可能出现异常情况的语句都包含在其间。在第二例中可以看到,还可以在异常发生时,统一做一些相应的处理,比如释放资源等。
在上面两例中,都有String的保护问题,String为什么需要进行非空检查?假如你写的方法里去获取str.length(),如果string为null的时候,就会抛出异常。
堆内存、栈内存
我们来看看其中最著名的异常之一:NPE
What is a NullPointerException, and how do I fix it?
Why do I get a NullPointerException?
左边的表达式是int基本数据类型,而右边则是Integer类。
int x;
这句表达式,java会自动赋初始值0,但是当Integer num;
时,java将num设为null,意思是I am pointing at nothing.
如果这个引用变量是null的情况下,你去调用它的方法,就会抛出NPE。要了解整个赋值过程,必须要对heap和stack有一个简要的理解:What and where are the stack and heap?
**stack **: local variables (including method parameters) are stored
heap: object variables, these are merely references (pointers) to the actual objects
String相关补充
先来看看String的两种赋值方式:
What is the difference between “text” and new String(“text”)?
-
String s = "text";
(string literal) -
String s = new String("text");
(string object)
** new String("text");** explicitly creates a new and referentially distinct instance of a String object;
String s = "text"; may reuse an instance from the string constant pool if one is available.
使用string literal方式进行赋值的时候,如果string constasnt pool中已经存在该值,则会复用string constasnt pool中的instance variable。所有string literal都是String类的实例,也就是说当你以string literal方式进行赋值的时候,是编译器来调用其构造函数。
The
String
class represents character strings. All string literals in Java programs, such as"abc"
, are implemented as instances of this class.
因此会有如下经典问题
String s1 = "foobar";
String s2 = "foobar";
System.out.println(s1 == s2); // true
s2 = new String("foobar");
System.out.println(s1 == s2); // false
System.out.println(s1.equals(s2)); // true
equals : checks the actual contents of the string
**== operator **: checks whether the references to the objects are equal
== 比较的是地址,equals比较的是实质的内容。stackoverflow上的网友给出的回答很赞,如果你是小王,你在北京和上海有两套房子,你两边的邻居都说“小王住在我隔壁”,如果用equals来比较小王,就是true,因为北京的小王和上海的小王都是小王。用==就是false,因为地址不一样。
其他资料
pythontutor 这个网站可以可视化调用
Should I learn Kotlin or stick to Java?
网友评论