您的位置:首页 > 编程语言 > Java开发

Kotlin学习笔记(一)—基础语法与Java全面PK

2018-02-09 15:53 183 查看

前言

Kotlin作为Google承认的新的Android开发语言必定有其可取之处。现在开始,我也要随波逐流,记录学习Kotlin的点点滴滴。同时,通过将Kotlin还原成Java代码,对比两种语言的优劣。当然,当你能将某个Kotlin知识点还原成Java就可以算你掌握了这个知识点。文章大部分通过官方文档学习而来,要想原汁原味的朋友可以点击下面链接:

Kotlin官网

1.函数定义

Kotlin定义函数方法有下面几种形式:

1.函数带两个参数和返回值:

fun sum(a:Int,b:Int):Int{
return a+b
}


对应Java代码:

int sum(int a,int b){
return a+b;
}


2.函数通过表达式推断函数返回值:

fun sum(a:Int,b:Int) = a + b


对应Java代码:

int sum(int a,int b){
return a+b;
}


3.函数无返回值或者说返回值无意义:

fun sum(a:Int,b:Int):Unit{
println("sum of $a and $b is ${a+b}")
}


or

fun sum(a:Int,b:Int){
println("sum of $a and $b is ${a+b}")
}


对应Java代码:

void sum(int a,int b){
System.out.println(String.format("sum of %d and %d is %d",a,b,a+b));

}


Tips:在字符串内$符号后带变量名代表这个变量的值,$符号后带{},代表{}里面表达式的值。Unit返回类型相当于Java里的void

4.函数参数含数组参数:

fun printArray(vararg args:Int){
for(arg in args){
print("$arg ")
}
}


or

fun printArray(args:Array<Int>){
for(arg in args){
print("$arg ")
}
}


对应Java代码:

void printArray(Integer...args){
for(Integer arg:args){
System.out.println(arg+" ");
}

}


2.定义常量和变量

1.Kotlin常量相当于Java里对变量添加final,定义时复制后将不能改变其值:

val a: Int = 1  // 直接定义时赋值
val b = 2   // 在常量声明时可不指定类型
val c: Int  // 定义时不赋值
c = 3       // 在其他地方才赋值


注意:第三种方式定义常量时必须要制定类型,否则编译出错。

对应Java代码

final int a = 1;
final int b = 2;
final int c = 3;


这里Kotlin和Java的区别就体现出来了,Java声明常量必须要给常量赋初值,必须指定常量的类型。而Kotlin可以不声明常量类型,并且可以延后给常量赋值,但需要声明常量类型。

3.注释

Kotlin的注释跟Java完全一样。

4.使用条件表达式

Kotlin使用条件表达式与Java的写法有出入,但效果没明显区别。

fun max(a:Int,b:Int):Int{
return if(a>b) a else b
}


or

fun max(a:Int,b:Int):=if(a>b) a else b


对应的Java代码

int max(int a,int b){
return a > b ? a : b;
}


5.可空的参数或返回值

Kotlin对于可空的参数和返回值,在声明参数类型后加?符号,表示参数可空。

fun toInt(s:String):Int?{
return s.toIntOrNull();
}


对应Java代码

@Nullable Integer toInt(String s){
return Integer.valueOf(s);
}


注意:在Java代码中Integer.value()方法若参数不可转为整形会crash。

6.检查类型

Kotlin在检查类型写法也与Java不同。Kotlin用is代替了Java的Instanceof。此外,如果变量被检查符合某种类型,无需进行强制转换,系统将自动将变量转换为那个类型。例如:

fun getStringLength(obj:Any):Int?{
if(obj is String){
//系统自动将obj转换为String类型
return obj.length
} else
//return obj.length  在此处使用obj.length将报错
return null
}


or

fun getStringLength(obj:Any):Int?{
if(obj !is String){
return null
//return obj.length 在此处使用obj.length将报错
} else
//系统自动将obj转换为String类型
return obj.length
}


对应的Java代码

@Nullable Integer getStringLength(Object obj){

e671
if(obj instanceof String){
String s = (String)obj;
return s.length;
}else{
return null;
}
}


7.遍历数组类型

Kotlin在遍历数组上与Java上也有区别,如下:

val items = listOf("apple", "banana", "kiwi")
for (item in items) {
println(item)
}


or

val items = listOf("apple", "banana", "kiwi")
for (index in items.indices) {
println("item at $index is ${items[index]}")
}


对应的Java代码

final String[] items = new String[]{"apple","banana","kiwi"};
for(String item:items){
System.out.println(item);
}


or

final String[] items = new String[]{"apple","banana","kiwi"};
int size = items.size;
for(int i = 0;i<size;i++){
System.out.printlin(String.format("item at %d is %s",i,items[i]));
}


8.while循环

Kotlin在用while循环与Java无任何区别。

9.范围检查

Kotlin相对于Java简化了数据范围检测的写法。如下:

1.检查数据是否在数值范围内

val x = 10
val y = 9
if (x in 1..y+1) {
println("fits in range")
}


对应Java代码

final x = 10;
final y =9;
if(x>=1&&x<=y+1){
System.out.println("fits in range");
}


2.检查数据是否在数值范围外

val list = listOf("a", "b", "c")

if (-1 !in 0..list.lastIndex) {
println("-1 is out of range")
}
if (list.size !in list.indices) {
println("list size is out of valid list indices range too")
}


对应Java代码

final Array<String> list = Arrays.asList("a","b","c");
if(-1 < 0||-1 > list.size()-1){
System.out.println("-1 is out of range");
}
if(list.size()<0||list.size()>list.size()-1){
System.out.println("list size is out of valid list indices range too");
}


通过上面的对比,Kotlin的代码效率就体现出来了。

3.遍历数值范围

for (x in 1..5) {
print(x)
}


对应的Java代码

for(int i=0;i<=5;i++){
System.out.print(x+"");
}


4.步进遍历数值范围

for (x in 1..10 step 2) {
print(x)
}
println()
for (x in 9 downTo 0 step 3) {
print(x)
}


对应的Java代码

int x;
for(x = 1;x<=10;x+=2){
System.out.print(x+"");
}
System.out.print("\n");
for(x=9;x>=0;x-=3){
System.out.print(x+"");
}


通过对比,Kotlin的代码简洁性又体现出来了。

10.when表达式

when表达式是Kotlin新增的用于多情况的取值判定。来见识一下他的威力:

fun describe(obj:Any):String =
when(obj){
1 -> "One"
"Hello" -> "Greeting"
is Long -> "Long"
!is String -> "isn't String"
else -> "Unknown"
}


对应的Java代码:

String describe(Object obj){
if(obj instanceof Integer && (int)obj == 1){
return "One";
}else if(obj instanceof String &&((String)obj).equal("Hello")){
return "Greeting";
}else if(obj instanceof Long){
return "Long";
}else if(!(obj instanceof String)){
return "isn't String";
}else{
return "Unknown";
}
}


我已经是尽量简洁的用Java代码还原,但是由于Java代码需要各种判定类型,强制转换,简洁性终究还是被Kotlin完胜。此外,when还能这样操作:

val a = "bbb";
val b = 5;
when{
a.equal("bbb") -> {
print("a is bbb")
print("a")
}
b == 5 -> print -> print("b == 5")
}


两种when的区别是前者是对()内的对象进行判定。后者是不指定对象。

11.集合操作

Kotlin对于集合的操作可谓是对Java代码的又一颠覆。对比一下:

1.判断对象是否在集合内

val fruits = setOf("apple","banana","orange")
if("apple" in fruits){
println("apple is in fruits")
}


而Java代码

final Set fruits = new HashSet();
fruits.add("apple");
fruits.add("banana");
fruits.add("orange");
if(fruits.contains("apple")){
System.out.println("apple is in fruits");
}


2.对集合的一系列操作

val fruits = listOf("banana", "avocado", "apple", "kiwi")
fruits
.filter { it.startsWith("a") }  //过滤非a开头的元素
.sortedBy { it }    //对集合排序
.map { it.toUpperCase() }  //重新映射
.forEach { println(it) }   //逐个操作集合元素


看到这代码是不是似曾相识。这分明就是RxJava换种写法。这种写法我们称作 lambda表达式,是一种链式操作。在filter{}等里面,有一个常量参数it代表当前元素。

用原生的Java写写看:

....//fruit的初始化
Set<String> tempSet = new TreeSet<>();
for(String fruit :fruits){
if(fruit.startWith("a")){
//遍历过程中不能对集合进行增删操作,否则容易出现异常
tempSet.add(fruit);
}
}
fruits.removeAll(tempSet);
Collections.sort(fruits);
for(String fruit:fruits){
String s = fruit.toUpperCase();
forEach(s);
}

void forEach(String s){
System.out.println(s);
}




12.类的继承和接口

Kotlin在继承类和接口实现上比Java有了很大的区别。其一,实例化对象不用加new。其二,Java写在构造器的参数在Kotlin可以在类声明时在类名后声明。其他的不可描述。

fun main(args: Array<String>) {
val rectangle = Rectangle(5.0, 2.0) //no 'new' keyword required
val triangle = Triangle(3.0, 4.0, 5.0)
println("Area of rectangle is ${rectangle.calculateArea()}, its perimeter is ${rectangle.perimeter}")
println("Area of triangle is ${triangle.calculateArea()}, its perimeter is ${triangle.perimeter}")
}

abstract class Shape(val sides: List<Double>) {
val perimeter: Double get() = sides.sum()
abstract fun calculateArea(): Double
}

interface RectangleProperties {
val isSquare: Boolean
}

class Rectangle(
var height: Double,
var length: Double
) : Shape(listOf(height, length, height, length)), RectangleProperties {
override val isSquare: Boolean get() = length == height
override fun calculateArea(): Double = height * length
}

class Triangle(
var sideA: Double,
var sideB: Double,
var sideC: Double
) : Shape(listOf(sideA, sideB, sideC)) {
override fun calculateArea(): Double {
val s = perimeter / 2
return Math.sqrt(s * (s - sideA) * (s - sideB) * (s - sideC))
}
}


用Java代码

.... // main函数省略

abstract class Shape{
private double perimeter;
Shape(List<Double> sides){
for(Double side :sides){
perimeter+=side;
}
}
abstract double calculateArea();
}

interface RectangleProperties {
boolean isSquare();
}

class Rectangle extends Shape{
double height;
double length;

Rectangle(double height,double length){
super(Arrays.asList(height,length,height,length));
this.height = height;
this.length = length;
}

@Override
boolean isSquare(){
return length = height;
}

@Override
double caculateArea(){
return height*length;
}
}

class Triangle extends Shape{
double sideA;
double sideB;
double sideC;

Triangle(double sideA,double sideB,double sideC){
super(Arrays.asList(sideA,sideB,sideC));
this.sideA = sideA;
this.sideB = sideB;
this.sideC = sideC;
}

double caculateArea(){
final double s = perimeter/2;
return Math.sqrt(s * (s - sideA) * (s - sideB) * (s - sideC));
}
}


对比一下可以发现,Kotlin在类的继承和接口实现的简洁性比Java有了很大的提升。其一、构造器参数在类声明时就已经声明并写入。其二,类声明的参数会被系统直接默认为类成员属性且无需逐个为其赋值。其三、接口可以声明变量常量,并在实现类上赋初值。其四、对象实例化不用加new了。

结语

Kotlin的基础语法与Java的对比上可以看到Kotlin的代码简洁性比Java强上不少。Kotlin为什么可以取代Java成为Android的官方开发语言通过阅读这篇笔记都有所体会吧。由于Kotlin和Java都是运行在JVM虚拟机上,所以两者之间可以互相调用。至于用哪种?你喜欢就好。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息