System.out.println(“fits in range”);
}12345
2.检查数据是否在数值范围外
val list = listOf(“a”, “b”, “c”)
if (-1 !in 0…list.lastInd
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
ex) {
println("-1 is out of range")
}
if (list.size !in list.indices) {
println(“list size is out of valid list indices range too”)
}12345678
对应Java代码
final Array 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”);
}1234567
通过上面的对比,Kotlin的代码效率就体现出来了。
3.遍历数值范围
for (x in 1…5) {
print(x)
}123
对应的Java代码
for(int i=0;i<=5;i++){
System.out.print(x+"");
}123
4.步进遍历数值范围
for (x in 1…10 step 2) {
print(x)
}
println()
for (x in 9 downTo 0 step 3) {
print(x)
}1234567
对应的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+"");
}12345678
通过对比,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”
}12345678
对应的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”;
}
}12345678910111213
我已经是尽量简洁的用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”)
}123456789
两种when的区别是前者是对()内的对象进行判定。后者是不指定对象。
11.集合操作
Kotlin对于集合的操作可谓是对Java代码的又一颠覆。对比一下:
1.判断对象是否在集合内
val fruits = setOf(“apple”,“banana”,“orange”)
if(“apple” in fruits){
println(“apple is in fruits”)
}1234
而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”);
}
12345678
2.对集合的一系列操作
val fruits = listOf(“banana”, “avocado”, “apple”, “kiwi”)
fruits
.filter { it.startsWith(“a”) } //过滤非a开头的元素
.sortedBy { it } //对集合排序
.map { it.toUpperCase() } //重新映射
.forEach { println(it) } //逐个操作集合元素123456
看到这代码是不是似曾相识。这分明就是RxJava换种写法。这种写法我们称作 lambda表达式,是一种链式操作。在filter{}等里面,有一个常量参数it代表当前元素。
用原生的Java写写看:
…//fruit的初始化
Set 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);
}123456789101112131415161718
12.类的继承和接口
Kotlin在继承类和接口实现上比Java有了很大的区别。其一,实例化对象不用加new。其二,Java写在构造器的参数在Kotlin可以在类声明时在类名后声明。其他的不可描述。
fun main(args: Array) {
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) {
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))
}
}12345678910111213141516171819202122232425262728293031323334
用Java代码
… // main函数省略
abstract class Shape{
private double perimeter;
Shape(List 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));
}
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
对比一下可以发现,Kotlin在类的继承和接口实现的简洁性比Java有了很大的提升。其一、构造器参数在类声明时就已经声明并写入。其二,类声明的参数会被系统直接默认为类成员属性且无需逐个为其赋值。其三、接口可以声明变量常量,并在实现类上赋初值。其四、对象实例化不用加new了。
结语
Kotlin的基础语法与Java的对比上可以看到Kotlin的代码简洁性比Java强上不少。Kotlin为什么可以取代Java成为Android的官方开发语言通过阅读这篇笔记都有所体会吧。由于Kotlin和Java都是运行在JVM虚拟机上,所以两者之间可以互相调用。至于用哪种?你喜欢就好。
kotlin基础语法
一、基础语法
- 不一样的类型声明:
val a:String = " i am kotlin";
2、类型推导
val a = " i am kotlin";
那么什么时候使用显示声明呢?
如果是函数的参数 必须用显示声明
如果是一个非表达式定义的函数 除了 返回Unit,其他情况必须使用
如果是一个递归函数,必须使用
如果有一个公有方法的返回值,建议使用(更好的代码可读性)
3、var val介绍
var声明变量 val类似于java的final不可变。
4、高阶函数
定义:高阶函数就是把其他函数作为参数或者作为返回值的函数。是更高级的抽象机制,极大的增强了函数的表达能力。
函数类型:(Int)->Unit
用->链接参数和返回类型,参数必须用()括起来,返回值类型即使是空的也要显示声明为Unit;
多个参数用逗号隔开;
(param:String?)->Unit 类型后边的 ?代表次参数可以为空;
函数作为参数 ((Int)->Unit)->Unit
函数作为返回值 (Int)->(Int)->Unit
双冒号语法 :: 用来引用类的变量和方法
匿名函数就是无需定义函数名称,其他的和普通函数定义语法一样,简而言之,匿名函数就是⼀个普通函数除了其名称省略了,其函数体也可以是表达式或代码块
5、lambda
例子:val sum:(Int x,Int y)->Int={Int x,Int y->x+y}
一个lambda表达式必须用{}来包裹;
如果lambda声明了参数部分的类型,且返回值类型支持推导,那么lambda变量就可以省略函数类型声明;
val sum={Int x,Int y->x+y}
如果lambda变量声明了函数类型,那么lambda表达式参数部分的类型就可以省略。
val sum:(Int x,Int y)->Int={x,y->x+y}
单个参数的隐式名称it(语法糖),listOf(1,2).forEach{print(it)}等价于listOf(1,2).forEach{it->print(it)};
如果lambda表达式要调用某个方法fun printKot(p:Int)={print(it)},则需要在传入表达式的方法后边加()去执行本方法,()其实就是执行了Function的invoke()方法;
示例:listOf(1,2).forEach{printKot(it)()};
6、区分fun函数声明和lambda表达式
1、代码块函数体:fun在没有等号只有{}的情况下,如果返回非Unit,必须带return;
fun foo(x:Int){print(x)}
fun foo(x:Int):Int{return x+2}
2、单表达式函数体:fun带有等号,这个可以省略return;
fun foo(x:Int):Int={x+2}
fun foo(x:Int):Int=x+2
注意:不管是val还是fun,如果是等号加{}的语法,那么构建的就是lambda表达式,lambda的参数在花括号的内部声明,如果左侧是fun那么就是lambda表达式函数体,也必须通过()或者invoke调用lambda。示例:
fun foo(x:Int,y:Int):Int={x+y} 调用 foo(1,2)或foo.invoke(1,2)
fun foo(x:Int):Int={y:Int->x+y} 调用 foo(1).(2)或foo(1).invoke(2)
3、闭包
在kotlin中,由{}包裹的代码块访问了外部环境变量则该代码块被称为一个闭包,一个闭包可以直接当做参数传递或者直接使用,可以看成是访问外部环境变量的函数,lambda表达式是常见的闭包形式。
介绍一种lambda自运行的方式{x:Int->print(x)}(1);
7、函数调用说明
如果参数有多个,且最后一个为函数,则可以按照如下方式调用:
fun foo(x:Int,y:Int,res:(Int,Int)->Int)){
res(x,y)
}
调用方式:
fun foo(1,2){
x,y->{return x+y}
}
8、表达式
可以是一个值、常量、变量、操作符、函数或者他们之间的组合,通俗的讲,表达式就是可以返回值的语句。
9、枚举
与java比kotlin的枚举就是一个类 多了class符号
enum class DayOfweek (val day:Int){
MON(1),
TUS(2)
;//如果以下有额外的方法或属性定义,则必须强制加上分号
fun getDayNum:Int{
return day
}
}
10、when表达式
结构 when else 组成,由花括号包含多个逻辑分支,每个分支由->链接;
when关键字的参数可以省略(这种情况下分支->左侧需返回boolean值,否则报错);
11、for循环和范围表达式
for in step downTo util 几个关键字的用法
for(i in 1…10 step 2) print(i);
倒序:for(i in 1…10 downTo 1 step 2) print(i);
var res= “a” in “abc”…“xyz”; in 、!in的用法
“a” ! in listOf(“a”,“b”,“c”);
12、中缀表达式
格式 A 中缀方法 B
注意:1、中缀方法必须是某个类的成员方法或者扩展函数
2、中缀方法必须只有一个参数,不可以多个,也不能是可变参数varargs
3、在方法前必须加infix关键字
class person {
infix fun call(name:String){
print(“my name is ${name}}.”);
}
}
调用方式
val p=Person();
p call “hello”
还可以跟普通语法一样调用 p.call(“hello”);
13、字符串
i in 1…10 step 2) print(i);
倒序:for(i in 1…10 downTo 1 step 2) print(i);
var res= “a” in “abc”…“xyz”; in 、!in的用法
“a” ! in listOf(“a”,“b”,“c”);
12、中缀表达式
格式 A 中缀方法 B
注意:1、中缀方法必须是某个类的成员方法或者扩展函数
2、中缀方法必须只有一个参数,不可以多个,也不能是可变参数varargs
3、在方法前必须加infix关键字
class person {
infix fun call(name:String){
print(“my name is ${name}}.”);
}
}
调用方式
val p=Person();
p call “hello”
还可以跟普通语法一样调用 p.call(“hello”);
13、字符串