前言
- 我个人使用的工具是Android Studio
- 写这篇文章呢,主要是熟悉了解kotlin
- kotlin教程:http://www.runoob.com/kotlin
- 不讲基本使用
-
查看kotlin字节码和转成java
基本语法
可变变量var和不可变量val
- val是不可变量而不是常量
val a=55
查看对应的Java
public final class KotlinKt {
private static final int a = 55;
public static final int getA() {
return a;
}
}
- 我们会发现它只有get方法而没有set方法。那么为什么说是变量呢?
val a=random.nextLong()
此时我们会发现,每次初始化的值是不一样的。但是值在初始化之后值就不能再改变
- var可变的变量
var a=55
对应的Java
public final class KotlinKt {
private static int a = 55;
public static final int getA() {
return a;
}
public static final void setA(int var0) {
a = var0;
}
}
因为有set方法,所以本身是可以改变的
- 如果想实现Java那种常量怎么办呢?
使用companion object+const
class A{
companion object{
const val TAG="TAG"
}
}
转成Java代码
@NotNull
public static final String TAG = "TAG";
NULL检查机制
Kotlin的空安全设计对于声明可为空的参数,在使用时要进行空判断处理,有两种处理方式,字段后加!!像Java一样抛出空异常,另一种字段后加?可不做处理返回值为 null或配合?:做空判断处理
那么kotlin代码是如何保证代码的空安全呢?
//类型后面加?表示可为空
var age: String? = "23"
var test= age?.length
转成Java(只看部分)
static {
String var10000 = age;
test = var10000 != null ? var10000.length() : null;
}
我们看到?的作用就是如果age为空,则返回null,否则执行age.length
//类型后面加?表示可为空
var age: String? = "23"
var test= age!!.length
转成对应的java
static {
String var10000 = age;
if (var10000 == null) {
Intrinsics.throwNpe();
}
test = var10000.length();
}
!!的作用实际就是进行判断,如果为null则抛出异常
?.的使用
val a:String?=null
val length=a?.length?:-1
转成对应的Java
String var10000 = a;
length = var10000 != null ? var10000.length() : -1;
?:实际也就是Java中三元运算符
类型检测及自动类型转换
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// 做过类型判断以后,obj会被系统自动转换为String类型
return obj.length
}
return null
}
//或者
fun getStringLength(obj: Any): Int? {
if (obj !is String)
return null
// 在这个分支中, `obj` 的类型会被自动转换为 `String`
return obj.length
}
转成对应的Java都是如下
public final class KotlinKt {
@Nullable
public static final Integer getStringLength(@NotNull Object obj) {
Intrinsics.checkParameterIsNotNull(obj, "obj");
return obj instanceof String ? ((String)obj).length() : null;
}
}
因此我们看到实际上Java会自动将obj转成对应的类型
区间
for (i in 1..4) print(i) // 输出“1234”
转成对应的Java
public final void main() {
int i = 1;
for(byte var2 = 4; i <= var2; ++i) {
boolean var3 = false;
System.out.print(i);
}
}
实际就是相当于
public final void main() {
for(int i=1; i <= 4; ++i) {
boolean var3 = false;
System.out.print(i);
}
}
所以..实际是个闭区间[],而downTo也是闭区间,而对应Java代码如下
int i = 4;
for(byte var2 = 1; i >= var2; --i) {
boolean var3 = false;
System.out.print(i);
}
until实际是左闭右开[)
int i = 1;
for(byte var2 = 4; i < var2; ++i) {
boolean var3 = false;
System.out.print(i);
}
可变长参数函数
fun vars(vararg v:Int){
for(vt in v){
}
}
转成对应Java
public final class KotlinKt {
public static final void vars(@NotNull int... v) {
Intrinsics.checkParameterIsNotNull(v, "v");
int[] var3 = v;
int var4 = v.length;
for(int var2 = 0; var2 < var4; ++var2) {
int var10000 = var3[var2];
}
}
}
实际就是
public final class KotlinKt {
public static final void vars(@NotNull int... v) {
//判空
int[] data=v;
for(int i= 0; var2 < v.length; ++var2) {
int a = data[var2];
}
}
}
基本数据类型
比较两个数字
- 在 Kotlin 中,三个等号 === 表示比较对象地址,两个 == 表示比较两个值大小。
==的源码
public open operator fun equals(other: Any?): Boolean
转成Java之后的代码最终调用的是
public static boolean areEqual(Object first, Object second) {
return first == null ? second == null : first.equals(second);
}
===对应Java代码
public static final void main() {
if (a == b) {
}
}
所以kotlin中的===实际是Java中的==
数组
var a = arrayOf(1, 2, 3)
@NotNull
private static Integer[] a = new Integer[]{1, 2, 3};
所以我们发现与 Java 不同的是,Kotlin 中数组是不型变的(invariant)
条件表达式
when表达式
fun f(x:Int){
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // 注意这个块
print("x 不是 1 ,也不是 2")
}
}
}
转成对应的Java
实际就是switch case并且会自动添加break
多个类型用法
fun f(x:Any){
when (x) {
1 ,3-> print("x == 1")
"2" -> print("x == 2")
}
}
转成Java
String var2;
boolean var3;
if (!Intrinsics.areEqual(x, 1) && !Intrinsics.areEqual(x, 3)) {
if (Intrinsics.areEqual(x, "2")) {
var2 = "x == 2";
var3 = false;
System.out.print(var2);
}
} else {
var2 = "x == 1";
var3 = false;
System.out.print(var2);
}
实际会转成Java中if判断
when中的in使用
val items = setOf("apple", "banana", "kiwi")
when {
"orange" in items -> println("juicy")
"apple" in items -> println("apple is fine too")
}
转成对应的Java
public static final void f(@NotNull Object x) {
Intrinsics.checkParameterIsNotNull(x, "x");
Set items = SetsKt.setOf(new String[]{"apple", "banana", "kiwi"});
String var2;
boolean var3;
if (items.contains("orange")) {
var2 = "juicy";
var3 = false;
System.out.println(var2);
} else if (items.contains("apple")) {
var2 = "apple is fine too";
var3 = false;
System.out.println(var2);
}
}
这里的kotlin中的in对应的实际是Java中的contains
循环
for循环
val items = listOf("apple", "banana", "kiwi")
for (item in items) {
println(item)
}
对应Java的代码
List items = CollectionsKt.listOf(new String[]{"apple", "banana", "kiwi"});
Iterator var3 = items.iterator();
while(var3.hasNext()) {
String item = (String)var3.next();
boolean var4 = false;
System.out.println(item);
}
这里的in实际是迭代器,对应的实际是Java中的while循环
val items = listOf("apple", "banana", "kiwi")
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
对应的Java的代码
List items = CollectionsKt.listOf(new String[]{"apple", "banana", "kiwi"});
int index = 0;
for(int var3 = ((Collection)items).size(); index < var3; ++index) {
String var4 = "item at " + index + " is " + (String)items.get(index);
boolean var5 = false;
System.out.println(var4);
}
这里我们就可以看到,实际上 items.indices对应的是Java的for循环
返回和跳转
- 在循环中 Kotlin 支持传统的 break 和 continue 操作符。
fun main(args: Array<String>) {
for (i in 1..10) {
if (i==3) continue // i 为 3 时跳过当前循环,继续下一次循环
println(i)
if (i>5) break // i 为 6 时 跳出循环
}
}
- Break 和 Continue 标签
在 Kotlin 中任何表达式都可以用标签(label)来标记。 标签的格式为标识符后跟 @ 符号,例如:abc@、fooBar@都是有效的标签。 要为一个表达式加标签,我们只要在其前加标签即可。
默认的时候
fun f(x:Any){
for (i in 1..100) {
for (j in 1..100) {
if (i==3) break
}
}
}
对应Java代码
public static final void f(@NotNull Object x) {
Intrinsics.checkParameterIsNotNull(x, "x");
int i = 1;
for(byte var2 = 100; i <= var2; ++i) {
int var3 = 1;
for(byte var4 = 100; var3 <= var4 && i != 3; ++var3) {
}
}
}
使用标签
fun f(x:Any){
loop@ for (i in 1..100) {
for (j in 1..100) {
if (i==3) break@loop
}
}
}
对应Java的代码
public static final void f(@NotNull Object x) {
Intrinsics.checkParameterIsNotNull(x, "x");
int i = 1;
for(byte var2 = 100; i <= var2; ++i) {
int var3 = 1;
for(byte var4 = 100; var3 <= var4; ++var3) {
if (i == 3) {
return;
}
}
}
}
所以加入标签,当i==3的时候直接退出了整个循环
标签和continue一起使用
loop@ for (i in 1..10) {
for (j in 1..3) {
if (i==3) continue@loop
}
}
对应Java代码
public static final void main() {
int i = 1;
for(byte var1 = 10; i <= var1; ++i) {
int var2 = 1;
for(byte var3 = 3; var2 <= var3 && i != 3; ++var2) {
}
}
}
标签中返回
默认使用
var ints= setOf("1",0,"2","3")
ints.forEach {
if (it == 0) return
print(it)
}
打印结果:1
实际相当于直接跳过循环
标签中返回
var ints= setOf("1",0,"2","3")
ints.forEach lit@ {
if (it == 0) return@lit
print(it)
}
对应Java代码
Iterator var3 = $this$forEach$iv.iterator();
while(var3.hasNext()) {
Object element$iv = var3.next();
int var6 = false;
if (!Intrinsics.areEqual(element$iv, 0)) {
boolean var7 = false;
System.out.print(element$iv);
}
}
实际就是当值不等于0的时候打印数据.
这里需要注意,在实际开发中我们只需要直接返回默认的隐式标签return@forEach即可
ints.forEach {
if (it == 0) return@forEach
print(it)
}