kotlin 的简洁性
1. Null-Safety 空安全
- 化空对象的处理(防止空指针)
Kotlin 的设计理念之一就是希望消除代码中 null reference
造成 NullPointerException
的危害。
在声明一个变量的时候,必须要指定它是否是可以为空的,可以为空和不可以为空将会是按照不同的类型处理,比如 String 和 String?是不同的类型
空安全特性在实际使用中确实能带来很大的好处,能够在语言层面强制要求开发者对所有的可能为空的变量进行处理,如此即可大大减少代码中繁琐的判空, 并尽可能避免 NullPointerException
的产生。
val userName = a?.b?.c?.d ?: ""
多了这么一块代码:
Intrinsics.checkParameterIsNotNull(name, "name");
public static void checkParameterIsNotNull(Object value, String paramName) {
if (value == null) {
throwParameterIsNullException(paramName);
}
}
2. 强制 setter 和 getter
- 属性访问,代替
Get/Set
方法
Java的规范写法中会提倡使用 setter 和 getter 的写法,而不是直接对熟悉进行访问。这样做的好处就不赘述了。只是这样写的话,会带来很多的样板代码,会在项目中出现大量的 setXXX 和 getXXX 样式的代码。而Kotlin则是直接在语法层面解决了这个问题。
Kotlin中把对熟悉的访问强制使用setter 和 getter,那怕看起来像是直接读取一个成员变量,其实本质上还是访问的它的 getter 方法。这样就直接封死了直接操作成员变量的路
//Kotlin代码
class User {
var name :String?=null
}
//Java代码
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
对应生成的 java 代码:
public final class User {
@Nullable
private String name;
@Nullable
public final String getName() {
return this.name;
}
public final void setName(@Nullable String var1) {
this.name = var1;
}
}
3. 默认构造函数
- Kotlin代码
class User(var name: String)
- Java代码
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name.toUpperCase();
}
public void setName(String name) {
this.name = name.toUpperCase();
}
}
kotlin 对应生产的 java 代码:
public final class User {
@NotNull
private String name;
@NotNull
public final String getName() {
return this.name;
}
public final void setName(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.name = var1;
}
public User(@NotNull String name) {
Intrinsics.checkParameterIsNotNull(name, "name");
super();
this.name = name;
}
}
4. 对象属性调用简化(使用with、apply、let等)
- Kotlin代码(可避免重复写对象的名字)
val user = User()
with(user)
{
name = "jerry"
age = 18
}
- Java代码
User user = new User();
user.setName("jerry");
user.setAge(18);
5. 安卓自动绑定xml文件中控件定义
不再需要使用 findViewById
或 ButterKnife
,使用样例:
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
.....
textView.text = "hello"
}
}
详细文档,可参考:《使用Kotlin Android Extensions代替ButterKnife和findViewById》
6. 简化Parcelable实现
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
@Parcelize
class User(var age: Int,var name: String): Parcelable
7. 简化单例对象构造
- Kotlin代码(定义类名时采用object即可)
object User
{
fun test()
{
}
}
- Java代码
public final class User {
public static final User instance = new User();
public void test() {
}
public static User getInstance() {
return instance;
}
private User() {
}
}
kotlin 生成的 java 代码:
public final class User {
public static final User INSTANCE;
public final void test() {
}
private User() {
}
static {
User var0 = new User();
INSTANCE = var0;
}
}
8.使用字符串模版简化字符串拼接
- Kotlin代码
val info = "name:$name,age:$age"
(new StringBuilder()).append("name:").append(name).append(",age:").append(age).toString();
- Java代码
String info = "name:" + name + ",age:" + age;
9. 使用 when
进行分支判断(替代Java中 switch
)
- Kotlin代码
var id = 1
when (id) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("id 不是 1 ,也不是 2")
}
}
另外kotlin还支持将同一类的条件写在一起,如 2,3 -> print("x == 2或者3")
- Java代码
int x = 1;
switch (x) {
case 1:
print("x==1");
break;
case 2:
print("x==2");
break;
default:
print("id 不是 1 ,也不是 2");
break;
}
10. Data class
App 通常需要一些基本的l类别來封装 Domain,而 Kotlin 的 data class 减少了 Java 中不可避免的样板代码,data class
compiler 自动生成 getter, setter, equals(), hashCode(), toString() 以及 copy() 等方法
data class User(val username: String, val age: Int)
fun main() {
val user = User("Jerry", 18)
val (username, age) = user
println("username:$username,age:$age")
}
public final class User {
@NotNull
private final String username;
private final int age;
@NotNull
public final String getUsername() {
return this.username;
}
public final int getAge() {
return this.age;
}
public User(@NotNull String username, int age) {
Intrinsics.checkParameterIsNotNull(username, "username");
super();
this.username = username;
this.age = age;
}
@NotNull
public final String component1() {
return this.username;
}
public final int component2() {
return this.age;
}
@NotNull
public final User copy(@NotNull String username, int age) {
Intrinsics.checkParameterIsNotNull(username, "username");
return new User(username, age);
}
// $FF: synthetic method
public static User copy$default(User var0, String var1, int var2, int var3, Object var4) {
if ((var3 & 1) != 0) {
var1 = var0.username;
}
if ((var3 & 2) != 0) {
var2 = var0.age;
}
return var0.copy(var1, var2);
}
@NotNull
public String toString() {
return "User(username=" + this.username + ", age=" + this.age + ")";
}
public int hashCode() {
String var10000 = this.username;
return (var10000 != null ? var10000.hashCode() : 0) * 31 + this.age;
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof User) {
User var2 = (User)var1;
if (Intrinsics.areEqual(this.username, var2.username) && this.age == var2.age) {
return true;
}
}
return false;
} else {
return true;
}
}
}
User user = new User("Jerry", 18);
String username = user.component1();
int age = user.component2();
String var4 = "username:" + username + ",age:" + age;
boolean var5 = false;
System.out.println(var4);
11. 协程coroutines
协程最主要的优点还不在于减少代码,而在于使调用逻辑简化,使得我们不必使用 AsyncTask
或者 RxJava
这样复杂的方案.
GlobalScope.launch {
doSomething()
withContext(Dispatchers.Main)
{
textView.text = "coroutines完成执行"
Toast.makeText(this@MainActivity, "coroutines hooray", Toast.LENGTH_SHORT).show()
}
}
12. Extension Functions:
JetBrains 在设计之初就考虑到我們很習习惯Java 中的一些以 Utils
结尾的工具类,像是 FileUtils
, StringUtils
等等。
Kotlin 中采用 extension 的概念来大幅增加可能性并缩减代码量