Helloworld
学习一门语言的第一句代码都是hello world。先学会打印日志,才能看到后续的运行结果、
日志的打印:println();
常量和变量
常量:
val(Value的简写),相当于java中的final
val index = 1;
val index : Int = 1;
变量:
var(Variable的简写),但不是具体的类型,而是一个“可变的类型”,赋值之后类型是确定的。
var index = 10;
var index : Int = 10;
那,什么时候改使用val、什么时候使用var呢?
这个很简单,除非你事先确定是变量,其他全部定义成val,到你要使用它为一个变量的时候再改成var
基本数据类型
java kotlin 说明
int Int 整型
long Long 长整型
short Short 短整型
float Float 单精度浮点型
double Double 双精度浮点型
boolean Boolean 布尔型
char Char 字符
byte Byte 字节
上面可以看出的是,kotlin是没有基本的数据类型的,都是包装类。
函数
关键字:fun(function的简称)
fun method(){
println("this is kotlin!");
}
一个最简单的函数,方法名是method。没有入参,也没有出参。
fun method(num : Int) :Int{
return num+1;
}
具有入参和出参的函数。
fun largeNun(num1 : Int, num2 : Int) : Int = max(num1,num2);
函数的简写、函数体只有一行的时候,可以直接用等号来连接,同时,不再需要return。
fun print(num: Int = 100, str: String) {
println("num is:$num,str is:$str");
}
带有默认参数值的函数。
print(str = "122", num = 0);
函数调用的时候,不需要一一匹配,可以指定参数名、
流程控制之if
kotlin和java的if基本完全一致,这里不做过多赘述、
如果方法体里面只有一个if,是同样可以简写的。
例如:
fun largeNun(num1 : Int, num2 : Int) : Int = if(num1 > num2) num1 else num2;
流程控制之when
kotlin里的when和java中的switch强很多。原来java里面的switch只能用int类型,
后面扩充了可以用String等类型,但是kotlin更强大,条件中可以加入各种判断。
fun getAge(name : String) = when(name){
"zhangsan" -> 12;
"lisi" -> {
println("lisi-age:");
18;
}
else -> -1;
}
这里需要说一下,java里面的switch不是强制需要default,
但是kotlin这里是需要else的、没有else的情况下编译会出错。
张三对应的是12,这里也只有一行,可以直接写。
下面的李四、就是多行的,需要用大括号括起来。
fun getAge(name : String) = when{
name == "wangwu" -> 28;
else -> -1;
}
when还可以用不带单数的用法、
流程控制之循环
kotlin中的while和java中的while循环基本一致,这里不赘述了。
来看看for循环
val range = 0..10;
上面这句的意思是,定义一个1-10的闭区间[1,10]
val range2 = 1 until 10;
上面这句的意思是,定义一个1-10的前开后闭区间[1,10)
for(index in range step 2){
println("index is:"+index);
}
不仅可以做循环,还可以做步进、
for(i in 10 downTo 1 step 2){
println("this is:"+i);
}
不仅可以做正向,还可以做负向的循环
类和对象
类,跟java一样,都是使用关键字class来标识,都是使用大括号来界定类的范围、
class Cat{...}
val c = Cat();
val c : Cat = Cat();
从上面两行代码可以看出的是,kotlin实例化一个对象,不需要new关键字。
继承
class CCat : Cat(){}
kotlin中的继承不需要extends关键字,而是使用冒号(:),
同时需要注意到的是,父类需要多家一个小括号、这在jva中是不需要的、
还需要注意的是,被父类需要用open修饰,否则不能被继承,不带open的类,相当于java中的final类。
构造函数
kotlin中的构造函数分为2种,主构造函数和次构造函数。
原始的写法:
class Person constructor(username: String, age: Int) {
private var username: String ;
private var age: Int;
init {
this.username = username
this.age = age
}
}
省略constructor后的写法,这种和上面原始的写法,一样,主观看起来也差不多。
class Person(username: String, age: Int) {
private var username: String ;
private var age: Int;
init {
this.username = username
this.age = age
}
}
省略init的写法,也就是直接在全局变量里面赋值。
tip:直接省去init后,不给全局变量赋值,是会报错的。
class Person(username: String, age: Int) {
private val username: String = username;
private var age: Int = age;
}
直接在构造器中声明形参。
class Person(private val username: String, private val age: Int) {}
空类可以不用花括号括起来,直接就这样
class Person(private val username: String, private val age: Int)
次构造器:constructor
当有主构造器的时候,次构造器一定要调用主构造器、
class Person(username: String, age: Int) {
val username: String;
val age: Int;
var sex: String = "";
init {
this.username = username;
this.age = age;
}
constructor(username: String, age: Int, sex: String) : this(username, age) {
this.sex = "";
}
}
也可以不需要主构造器,只有次构造器。
多个次构造器直接也可以相互调用。
class Person {
var username: String = "zhangsan";
var age: Int = 9;
constructor(username: String) {
this.username = username;
}
constructor(username: String, age: Int) : this(username){
this.age = age;
}
}
接口
interface man{
fun eat();
fun run();
}
class Person : man{
override fun eat() {
}
override fun run() {
}
}
上面的例子可以看出,接口的定义和java中,没什么区别,还是方法的定义,需要fun关键字罢了、
接口的实现、java中使用implement关键字,但是kotlin中和继承一样,统一使用冒号:,中间用 逗号隔开。
同时还有一个细节的地方需要注意的是,kotlin方法的覆盖,也是使用override关键字,不同的是,它是在fun关键字之前。
kotlin中的修饰符和java中的修饰符
修饰符 JAVA Kotlin
public 所有类可见 所有类可见、默认
private 当前类可见 当前类可见
protect 当前类/子类/同包 当前类/子类
default 同包可见 无
internal 无 同一模块可见
data类
data class Bean(val name: String)
也就是java中的实体类、
这里有一个特点。
1、默认是final的。
2、会自动帮你生成equals、hashCode、toString等函数
object类
object Person {
fun check() {
println("username:");
}
}
Person.check();
object类,和java中的单例,是一样的,kotlin实现单例只需要加上关键字object即可、
这里不需要class关键字,只需要object即可、
调用的时候,直接类名.方法名、和我们使用静态的方法是一样的,
但这里kotlin默认已经new了一个全局的单例对象。
集合list、set、map
集合的初始化,在java中先要new一个集合对象,再一个一个的add进去。
而kotlin可以一行代码搞定
val man = listOf<String>("123", "456", "789");
建立一个list的集合,里面有3个元素。
但是、这种集合是不可变的,更像是数组。
val man = mutableListOf<String>("123", "456", "789");
这样初始化的集合,后续是可以对集合进行任意操作的。
同理,set和map集合也是一样的。
val man = setOf<String>("123", "456", "789");
val man = mutableSetOf<String>("123", "456", "789");
map的集合是键值对,所以,写法有点不一样,其实本质上还是一样的。
val man = mapOf<String, Int>("123" to 1, "456" to 2, "789" to 3);
val man = mutableMapOf<String, Int>("123" to 1, "456" to 2, "789" to 3);
空安全
fun say(content: String) {
println(content);
}
当你调用say方法的时候,参数是不能为空的<say(null)、这样会报错,不能通过编译>。
但是,有些时候需要空呢?
fun say(content: String?) {
println(content);
}
当在入参类型后面加上?、则可以传空的参数。
Java中判空是这样子的
if(man!=null){
man.say();
}
kotlin中判空
man?.say();
代码很简洁,对象后面加一个?、则表示,在执行后续操作的时候,先判断一下空,如果为空则不执行,不为空则执行。
val c = if (a != null) {
a;
} else {
b;
}
这段代码的意思很简单,如果a是空的话,则把b的值给c、a不为空则a的值给c。
kotlin可以简化成这样:
val c = a ?: b;
fun getTxtLen(txt: String?) = txt?.length ?: 0;
?. 和 ?: 结合使用、这个方法也很简单,当txt为空的时候就返回0,不为空的时候,返回的是txt的长度。
非空断言!!
一个对象后面加上!!则表示,这个对象,一定不会为空。
Kotlin 是静态语言还是动态语言
是静态语言
因为它是编译型的语言,而不是解释型的语言。
虽然在声明变量的时候没有确定类型,由后续的赋值来推断类型,但是编译的时候,一定是确定类型的,而不是可变类型的。
js是解释性的语言,js的变量是类型可变的,它才是动态的。
Lambda
var fun(Stirng,String) -> Unit = {as,bs -> println("astr:$as,bstr:$bs")}
var fun2 = {println("this is print")}
//使用it去引用传入的参数,条件是只有一个参数的时候
var fun3 : (String) -> Unit = { println("your input is: $it")}
var fun4 : (Int) -> Unit = {
when(it){
1 -> println("this is 1")
in 20 .. 30 -> println("this is 20 ~ 30")
else -> println("else condiction")
}
}
//使用别名去引用参数
var fun5 : (Int , Int) -> Unit = {aN,bN ->
println("first:@aN, second:$bN")
}
//方法的入参有两个,但是可以只接收一个,另一个用下划线替代
var fun6 : (Int Int) - > Unit= {aN, _ ->
println{"this is $aN"}
}
//这个表示传入一个string类型的参数,这个参数名字是str,返回值也是string类型, -> 后面的就是返回值
//这个方法的意思是传入任何一个字符串,我原样给你返回。
var fun7:(String) ->String= {str -> str}