本来嘛在IDEA的KotlinEDU已经完成一大半的入门小测试了,但换了电脑,IDEA更新成2017的后,发现KotlinEDU好像只支持2016版的,无奈,而且导入koans会有maven引起的错误,我又不会解决,只好在网页版的来了,既然要重头来,那就记录记录咯?反正加强印象
我们从Examples看起(如果看过kotlin官方文档那这些Example看起来会更容易,当然如果没看过我觉得还是能看得懂的)
HelloWorld
先从提供的例子入手了解一下基础语法吧
1.Simplest version
最简单的莫过于输出一个HelloWorld
/**
* We declare a package-level function main which returns Unit and takes
* an Array of strings as a parameter. Note that semicolons are optional.
*/
fun main(args: Array<String>) {
println("Hello, world!")
}
从注释开始看,这里提到我们声明的方法是包级别的,返回的类型是Unit,使用的参数是一个string数组,而且!分号是可有可无的
这里和Java有什么对比呢?
1.没有类,可以直接声明一个方法,这个方法就是包级别的
2.有默认返回值---Unit,不像java中的没返回值是void,关于Unit我们在后面再慢慢了解
3.println直接以行的形式打印,比System.out.println简洁多了
2.Reading a name from the command line
/**
* Line 13 demonstrates string templates and array access.
* See this pages for details:
* http://kotlinlang.org/docs/reference/basic-types.html#strings
* http://kotlinlang.org/docs/reference/basic-types.html#arrays
*/
fun main(args: Array<String>) {
if (args.size == 0) {
println("Please provide a name as a command-line argument")
return
}
println("Hello, ${args[0]}!")
}
在13行这里输出一个字符串,我们可以以${}的形式直接将一个参数以toString的方式输出
//如果args[0]="zhangsan",那么:
println("Hello, ${args[0]}!")----Hello,zhangsan
//如果有val name="zhangsan",那么:
println("Hello,$name")----Hello,zhangsan
3.Reading many names from the command line
/**
* Line 2 demonstrates the for-loop, that would have been called "enhanced"
* if there were any other for-loop in Kotlin.
* See http://kotlinlang.org/docs/reference/basic-syntax.html#using-a-for-loop
*/
fun main(args: Array<String>) {
for (name in args)
println("Hello, $name!")
}
(挺奇怪的,前一个例子中说的第13行是包含注释,这个例子的的第2行又是从非注释开始算)
这个例子展示的是kotlin的增强for循环,args是数组,name是一个形参,这样写就能遍历args输出所有的Hello,Xxx
4.A multi-language Hello
/**
* In this example, `val` a declaration of a read-only local variable,
* that is assigned an pattern matching expression.
* See http://kotlinlang.org/docs/reference/control-flow.html#when-expression
*/
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"
})
}
这个例子中,'val'表示的是一个只读的变量
在kotlin中,有两种变量的声明形式,一个是var,一个是val
val:是一个只读的变量
var:是一个可读可写的变量
好玩的还在后头,println里面居然可以不传字符串而是写了一个表达式,还是一个在java里没见过的表达式,理解倒是挺好理解的:
将获取的language进行判断,当其匹配上下面的字段时,则输出对应的字符串,否则就给个友好提示
when表达式是java中switch的进化版,switch的写法还是比较死板的,对我来说when更简洁明了(但初用起来还是有点不适应,除了简单的如例子中匹配上字符串,还能和别的表达式一起用)
5.An object-oriented Hello
/**
* Here we have a class with a primary constructor and a member function.
* Note that there's no `new` keyword used to create an object.
* See http://kotlinlang.org/docs/reference/classes.html#classes
*/
class Greeter(val name: String) {
fun greet() {
println("Hello, ${name}");
}
}
fun main(args: Array<String>) {
Greeter(args[0]).greet()
}
在这个例子中,我们有一个类带着主构造函数和一个成员方法,我们是不需要用'new'关键字去创建一个对象的!
在这第五个例子中终于见到对象了,在kotlin中创建类的写法和java中也是不同的;
在kotlin里构造函数可以直接跟在类名后面的小括号里,并且这个跟在类名后的小括号中的是主构造函数(对的,有主就有次,还有次级构造,但这里没提到就后面遇到再说)
该类中除了一个主构造函数,还有个成员方法,在成员方法中也是可以直接使用该类的成员变量的(在kotlin中是不是应该用成员变量这个说法?如果有错以后知道了再改正)
Basic syntax walk-through
Use a conditional expression
/**
* `if` is an expression, i.e. it returns a value.
* Therefore there is no ternary operator (condition ? then : else),
* because ordinary `if` works fine in this role.
* See http://kotlinlang.org/docs/reference/control-flow.html#if-expression
*/
fun main(args: Array<String>) {
println(max(args[0].toInt(), args[1].toInt()))
}
fun max(a: Int, b: Int) = if (a > b) a else b
if是一个表达式,所以它能返回一个值,他在这里可以很好的充当一个三元运算符的角色
这个例子中展示了一个方法可以在其后面用'='号拼接一个表达式,不需要用到大括号,相当于说我用if判断完,如果成立则返回前一个值,else则返回后一个值
Null-checks
/**
* A reference must be explicitly marked as nullable to be able hold a null.
* See http://kotlinlang.org/docs/reference/null-safety.html#null-safety
*/
package
// 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")
}
}
}
null检查也是kotlin区别于java最大的特点了,在kotlin中,一个变量必须明确的被标记为可以为null那它才能够为null
我们先看一眼parseInt方法:
// 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
}
在方法声明上,我们指定返回值为Int时,还在Int后面跟了一个'?'号,在这里,'?'号表示的是我这个parseInt方法,它的返回值可以是Int也可以是null
再继续看方法体,在kotlin中自带的基本类型扩展方法很帅,比如上面的str.toInt(),非常确切的面向对象方法,将一个str转换成Int,对,这是kotlin的各种基本类型自带的方法,大家可以玩玩看
在出异常的情况下,我们就返回一个null(说起来kotlin没有编译时异常检查,我觉得这个很不舒服,出异常的机会那么多,让开发者自己来try catch多累啊)
看完parseInt接着看main函数中的内容:
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")
}
}
}
我们在第5第6行可以看到通过parseInt方法我们获取到了x和y,这里获得的是一个可能为null的值
所以在下面想调用的话,编译器强制要求我们判断它两是否为null,为啥呢?因为他们可能为null呀
is-checks and smart casts
/**
* 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
}
'is'操作符能用来检查一个表达式是否是一个类型的实例;
如果我们通过'is'来检查一个不可变的变量或属性,那么我们就不需要去明确的将其转换成检查的类型(对的,kotlin会智能转换的);
例如例子里的getStringLength方法,传入了Any类型的对象(kotlin里没有Object类,最上层的类好像是Any)
我们在方法中判断它是否是String,如果是的话,不需要进行一个明确的类型转换声明,kotlin已经知道它是String了,我们就可以直接return 它的length
Use a while-loop
/**
* `while` and `do..while` work as usual.
* See http://kotlinlang.org/docs/reference/control-flow.html#while-loops
*/
fun main(args: Array<String>) {
var i = 0
while (i < args.size)
println(args[i++])
}
官方表示:kotlin里的while和do..while和java没啥区别,不多说
Use a for-loop
/**
* For loop iterates through anything that provides an iterator.
* See http://kotlinlang.org/docs/reference/control-flow.html#for-loops
*/
fun main(args: Array<String>) {
for (arg in args)
println(arg)
// or
println()
for (i in args.indices)
println(args[i])
}
for循环能迭代任何可以提供迭代器的东西
这里好像也没什么好说的?硬要说些什么的话:
在第一个for循环中他能智能识别到我们想要遍历的迭代器中的对象是什么,不需要像java中的增强for循环需要我们来声明出遍历的对象是什么
Use ranges and in
/**
* Check if a number lies within a range.
* Check if a number is out of range.
* Check if a collection contains an object.
* See http://kotlinlang.org/docs/reference/ranges.html#ranges
*/
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")
}
这个例子中有三个小例子,先看第一个吧:
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} ")
首先我们可以用if来判断一个参数是不是在一个范围中,太简单了没什么好讲的啊?
然后也可以在一个范围中进行迭代
再看第二个:
//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")
}
这个就有意思多了,我们能通过in操作符来判断一个集合是否包含一个对象,("ddd" in array)相当于调用了array.contans("ddd"),这段代码看起来是理所当然的,但要自己写我觉得不能一下子想起来
Use when
/**
* See http://kotlinlang.org/docs/reference/control-flow.html#when-expression
*/
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() {
}
when操作符用起来很爽,进化了的switch,能判断是否相同,能进行类型判断,还有一个else来处理别的情况,相当于default
when语句也能判断范围,例如我下面这个,但我不知道如何才能用when操作符判断其是否大于一个数字
in (10..Int.MAX_VALUE) -> println("bigger than 10 and smaller than Int.MAX_VALUE")