Kotlin快速入门(1) -- 与Java的对比学习
来源:互联网 发布:吉林网络教育 编辑:程序博客网 时间:2024/06/08 15:23
本篇博客 按照Kotlin官方文档,总结出了Kotlin与Java相比,常用语法的不同之处,方便快速入门Kotlin,本人才疏学浅,如有错误还请指正。
基础语法
1.定义变量:
Kotlin中的基本数据类型和Java差不多,只是形式上每种数据的首字母都是大写的: Int
Long
Short
Byte
Float
Double
不可变(只读)的变量
Java
final int a = 1;
kotlin
val a = 1
val a : Int = 1
在Kotlin中,变量如果被初始化了,他的值是可以被推导出来的,所以这里既可以不指定他为Int类型,让编译器自己去推导,也可以显式指定出来。
此外,Kotlin中每句话结尾可以不使用分号!
可变的变量
Java
int a = 1
Kotlin
var a = 1
var a : Int = 1
在Kotlin中,val用于修饰不可变的(只读)变量,就类似于Java中的final关键字,var用于修饰可变的变量,就类似于Java 中的普通的变量。 与 Java不同的是变量的名字在前面,变量的类型在后面,中间要以:
隔开。
此外,在Kotlin中一条语句的结尾可以不用写;
,当然如果写上也不会报错。
2.定义函数:
Java
public void eat(String food){ System.out.println("I like eat "+ food);}
这样一个简单的Java方法对应到Kotlin中的语法如下:
kotlin
public fun eat(food : String) : Unit{ println("I like eat $food")}
当然,在kotlin中如果没有显示制定访问修饰符,那么默认为public
,这就意味着这里的public
可以省略,这里的Unit
就对应于Java中的void
,但在Kotlin中,如果没有返回值,那么Unit
也是可以省略的,即下面这种形式:
fun eat(food : String){ println("I like eat $food")}
$
dollar符号是模板表达式开始的标志,这里可以理解为“取出变量food的值”,值得注意的是,Java中的System.out.println()
在Kotlin中变成了println()
,这和C语言中的输出函数的名字一样了。
此外,函数的参数还可以有默认值:
public fun eat(food : String = "Apple") : Unit{ println("I like eat $food")}
3.字符串模板
字符串可以包含一个模板表达式,它的结果会被连接到字符串中,在Java中,会用+
号来达到类似的效果。
Java
String animal = "dog";System.out.println("There is a "+ animal);System.out.println("Dog has "+animal.length()+"words");
Kotlin
val animal = "dog"println("There is a $animal")println("Dog has ${animal.length} words")
如果$
后面跟的不再是一个变量,就要加上{}
来表示取这个式子的值
4.数组
Kotlin中的数组和Java中的区别有点大,在Kotlin中Array 类代表着数组,[]
可以用于访问数组的元素,实际上 []
被进行了操作符的重载,调用的是 Array 类的 setter
和 getter
方法
创建一个数组有三种方式:
(1)通过指定大小,使用arrayOfNulls
直接创建一个空数组:
var ages = arrayOfNulls<Int>(3)
(2)使用xxxArrayOf
创建并初始化数组:
var ages = intArrayOf(19,20,21)
(3)使用lambda创建并初始化数组:
var ages = IntArray(3, { i -> i + 19 })for (j in ages) println("$j")
结果是:
192021
或者直接这样写:
var ages = Array(3, { i -> i + 19 })
Kotlin会自动根据lambda表达式的里面建立的映射关系推断出数组的类型。
5.流程控制语句
if
在Kotlin中,if是带有返回值的表达式,因此在Kotlin中没有三目运算符(x + y > 0 ? true : flase)
,就用if
就可以实现。
Kotlin中作为表达式的用法(这种情况必须带有else
分支语句):
val num = if(a > b) a else b
特别的是,if分支可以作为块,最后一个表达式是该块的值:
val num = if (a > b){ print("Hello! My value is a ") a}else{ print("Hello1 My value is b") b}
when
在Kotlin中没有switch语句了,取而代之的是when。
基础用法
Java:
switch (a){ case 1: System.out.println("I am 1"); break; case 2: System.out.println("I am 2"); break; case 3: System.out.println("I am 3"); break; default: System.out.println("I am default"); break;}
Kotlin:
when(a){ 1-> print("I am 1") 2-> print("I am 2") 3-> print("I am 3") else -> print("I am default")}
在Java中,case后面只能跟常量表达式,而在Kotlin中却可以用任意的表达式(包括含有in
,is
的表达式):
var b = "abcde"when(a){ b.length-> print("My length is b.length.") else -> print("I am default.")}
for
普通for循环
Java:
// 打印0到10for (int i = 0;i<=10;i++){ System.out.println(i);}
Kotlin:
//打印0到10for (i in 0..10){ println(i)}
在Kotlin中,for循环的形式变成了使用in关键字加上范围。
“foreach”循环
Java:
String[] list = new String[11];for (int i = 0;i<=10;i++){ list[i] = i+"";}//打印0到10for(String s : list){ System.out.println(s);}
Kotlin:
//初始化一个String类型的数组val list : Array<String> = Array(11,{index -> index.toString()}) for (e in list){ println(e)}
6.break、continue 、return
break 结束最近的闭合循环
continue 跳到最近的闭合循环的下一次循环
return 返回函数的值或终止函数函数运行
标签的格式为标签名@
在 break 和 continue 中使用标签
Java:
//用"out"作为外层循环的标记out: for (int i = 0; i < 100; i++) { for (int j = 0; j < 100; j++) { if (j==10) break out; System.out.println("i="+i+"j="+j+" "); }}
Kotlin:
out@ for (i in 1..100){ for (j in 1..100){ if (j==10) break@out print("i=$i,j=$j ") }}
continue配合标签的使用和break类似。
Kotlin 中的表达式可以添加标签,标签通过 @
结尾来表示,通过标签就可以实现 break 或者 continue 的快速跳转。
return标签
Kotlin:
先来看看forEach的实现原理:
/** * Performs the given [action] on each element. */public inline fun <T> Array<out T>.forEach(action: (T) -> Unit): Unit { for (element in this) action(element)}
forEach的参数是一个名为action的函数,内部使用一个for循环来遍历调用forEach的数组,并执行action函数。所以,可以把forEach的参数理解为一个匿名函数。
下面来看一个return使用场景:
fun test() { val list: Array<String> = Array(11, { index -> "${index.toString()}" }) list.forEach { if (it == "3") return println(it) }}
输出的结果是:
012
可以看到,一个return
直接返回出了test()
函数。但是如果我并不想返回到直接包围return
的test函数,我只想返回到当前这个lambda表达式(匿名函数)的时候,就要使用标签了,这种效果类似于在循环中使用了continue
(但是Kotlin中的forEach
中不能使用continue
)。
fun test() { val list: Array<String> = Array(11, { index -> "${index.toString()}" }) list.forEach inner@{ if (it == "3") return@inner println(it) }}
输出的结果是:
01245678910
当然,还可以使用隐式标签,这样更方便,该标签与接受该 lambda 的函数同名。
fun test() { val list: Array<String> = Array(11, { index -> "${index.toString()}" }) list.forEach { if (it == "3") return@forEach println(it) }}
类
1.类的声明和构造函数
Kotlin中的类也是用class声明,类的声明包含类名,类头(指定类型参数,主构造函数等等),以及类主体,用大括号包裹,类头和类体是可选的。
class A {}
如果没有类体可以省略大括号:
class EmptyClazz
Kotlin中的构造函数和Java中的构造函数的作用是一样的,但形式有所区别:
Java:
class Hello{ public Hello(){ System.out.println("Hello world!"); } public Hello(String content){ System.out.println("Hello "+ content); }}
在Java中构造函数可以有多个重载,而在Kotlin中,构造函数则分为“主构造函数”和“二级构造函数”,类可以有一个主构造函数以及多个二级构造函数
Kotlin:
class Hello constructor(content : String?){ init { println("Hello ${content}") } constructor() : this(null) { println("Hello world") }}
主构造函数是放在类头中的,用 constructor
关键字标示,但如果没有注解或者可见性说明,也可省略constructor
,主构造函数是不能包含初始化代码的,它的初始化需要放在init{}
代码块中执行。
当然如果在参数前面添加了var
或val
,则参数可直接变为类中的字段:
class Hello constructor(val content : String) { fun sayHello(){ println("Hello"+content) }}
此外如果主构造函数的参数可以用在初始化块内,那么他也可以在属性声明时直接赋值给属性,如:
class Hello constructor(content : String) { val a = content}
二级构造函数需要以constructor
constructor(age : Int) { println("Hello, I am $age")}
需要注意的是,如果类有主构造函数,每个二级构造函数都要使用this
关键字直接或间接通过另一个二级构造函数调用主构造函数。
class Hello constructor(name : String) { constructor(name: String,age : Int) : this(name) { println("Hello,I am $name , $age years old") }}
2.类的修饰符
属性修饰符(classModifier)
属性修饰符用于标示类本身的特性,这是Java是类似的:
abstract //抽象类标示 final //标示类不可继承,默认属性 open //类可继承,类默认是final的 enum //标示类为枚举 annotation //注解类
访问修饰符(accessModifier)
访问修饰符用于确定类的访问范围,这也和Java是类似的:
private //只在该类(以及它的成员)中可见 protected //只在该类(以及它的成员) 或 子类 中可见 internal //同一个模块(module)中可见 public//默认,任何地方都可见
3.创建类的实例
Kotlin中没有new关键字!!!
Kotlin中没有new关键字!!!
Kotlin中没有new关键字!!!
重要的事情说三遍!!!
Kotlin中直接通过类名就可以实例化一个类:
val invoice = Invoice()val customer = Customer("Joe Smith")
4.继承
Kotlin 中所有的类都有共同的父类 Any ,它是一个没有父类声明的类的默认父类:
class Example // 隐式继承于 Any
Any 不是 java.lang.Object,事实上它除了 equals(),hashCode()以及toString()外没有任何成员了。
在继承一个父类时候,Java使用的是extends
关键字,而Kotlin则使用了冒号:
,如果父类有构造方法,子类还必须创建构造方法,并使用super
关键字,调用父类的构造方法:
Java:
class A extends Base{ public A(String content) { super(content); }}
而在kotlin中,如果父类有构造方法,则在继承的时候就传值给父类即可:
Kotlin:
open class Base (content : String)class A(content: String) : Base(content)
需要注意的是,类的默认修饰符是final
,所以必须用open
修饰父类,它才可以被继承。
5.重写方法
在继承的时候,如果要重写父类的方法,必须在方法前加上override
,并且,只有被open修饰的方法才可以被重写:
open class Base { open fun v() {} fun nv() {}}class Derived() : Base() { override fun v() {}}
这里的nv()
由于没有用open
修饰,就无法被子类重写。
6.重写属性
重写属性和重写方法类似,都必须加上override
open class Foo { open val x: Int get { ... }}class Bar1 : Foo() { override val x: Int = ...}
7. 实现接口
Kotlin中实现接口和继承类一样,都是使用的:
interface MyInterface{ fun bar() fun app(){ //如果接口中的函数有函数体,则实现的时候可以不用重写 }}class May : MyInterface{ override fun bar() { }}
8.重写规则
在 Kotlin 中,实现继承通常遵循如下规则:如果一个类从它的直接父类继承了同一个成员的多个实现,那么它必须复写这个成员并且提供自己的实现(或许只是直接用了继承来的实现)。为表示使用父类中提供的方法我们用super<Base>
表示:
open class A { open fun f () { print("A") } fun a() { print("a") }}interface B { fun f() { print("B") } // 接口的成员变量默认是 open 的 fun b() { print("b") }}class C() : A() , B { // 编译器会要求复写f() override fun f() { super<A>.f() // 调用 A.f() super<B>.f() // 调用 B.f() }}
常见的类
1.嵌套类
一个类可以嵌套在其他类中:
class Outer { private val bar: Int = 1 class Nested { fun foo() = 2 }}val demo = Outer.Nested().foo() //==2
2.内部类
Kotlin中的内部类必须用inner
标示出来:
class Outer { private val bar: Int = 1 inner class Inner { fun foo() = bar }}val demo = Outer().Inner().foo() //==1
3.匿名内部类
Kotlin中的匿名内部类的形式相对于Java也有所变化:
Java:
window.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { //... }});
Kotlin:
window.addMouseListener(object: MouseAdapter() { override fun mouseClicked(e: MouseEvent) { // ... })
其实,Kotlin的匿名内部类的实例是通过“对象表达式”创建的。
4.数据类
Kotlin中的数据类的概念就成对应于Java中的JavaBeen,但它又比JavaBeen要简单得多。
Java:
public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }}
Kotlin:
data class Person(val name: String, val age :Int)
编译器会自动根据主构造函数中声明的所有属性添加如下方法:
equals()/hashCode 函数
toString 格式是 “Person(name=john, age=42)”
copy() 函数
[compontN()functions] //解构声明
- Kotlin快速入门(1) -- 与Java的对比学习
- Kotlin学习笔记(二):Kotlin与Java对比
- Kotlin学习总结(1)——Kotlin快速入门
- Kotlin笔记(二) : Kotlin与Java对比
- Kotlin escape与Java对比
- Kotlin学习笔记——与java对比
- kotlin 和java 的对比
- Java to Kotlin(java 与 Kotlin对比)
- Kotlin入门篇(三),Kotlin中字符串的对比
- kotlin第二讲 与 java对比
- 荐书 | Kotlin开发快速入门与实战
- java 转 Kotlin 快速入门①
- Kotlin 快速入门
- 2.2 Kotlin的Hello Word程序与Java的Hello World的class文件对比
- Android开发,Kotlin的了解与学习(八)-----kotlin与java的互相调用
- Objective-c 与java 的对比学习
- python与java的对比学习(一)
- Kotlin开发语言学习(3)Kotlin与Java混编
- 【Junit】之 仿 junit 3.8.1 写 lite-junit
- 修改PHP上传SIZE限制
- JSON Web Token
- 利用jenkins+maven部署java应用到远程服务器
- 【JSOI2008】星球大战 (并查集)
- Kotlin快速入门(1) -- 与Java的对比学习
- 逻辑回归和线性回归区别
- Java中的四种内部类
- Maven的pom.xml文件解析
- Oracle 10G dataguard 备库诊断脚本
- iOS安装包瘦身指南
- HDU 2043
- 【C#练习】基础知识订正
- Hibernate 简单用法