What is Kotlin
Kotlin
It is a language that runs on JVM
top of .
It Jetbrains
was created by , the company behind Jetbrains
many powerful tools such as the well-known . is a very simple language, one of its main goals is to provide a powerful language while maintaining a simple and streamlined syntax.Java IDE IntelliJ IDEA
Kotlin
kotlin features
Its main features are as follows:
- Lightweight: This is
Android
very important for. The libraries required by the project should be as small as possible.Android
There is a strict limit on the number of methods, andKotlin
only about 6000 additional methods have been added. - Interoperability: Communicates seamlessly
Kotlin
withJava
languages. This means that we canKotlin
use any existingJava
library in our code; therefore, even though the language is still young, there are already hundreds of libraries available. In addition to this,Kotlin
code can beJava
used by code, which means we can use both languages to build software. You can use itKotlin
to develop new features while implementingJava
other parts of the code base. - Strong typing: We rarely need to specify types in our code because the compiler can infer the type of a variable or function return value in most cases. This way you get two benefits: simplicity and security. Using
var
declaring a variadic argument,val
declaring an immutable argumentvar
:var
is a mutable variable, which is a variable that can be changed to another value by reassignment. This way of declaring variablesJava
is the same as declaring variables in .val
:val
is a read-only variable. This way of declaring a variable is equivalent to the variablejava
infinal
. Oneval
must be initialized when it is created because it cannot be changed later. The above code: var name = "ztz" println(name) name = "yif" println(name) val finalValue = "i v"; println(finalValue); The result is as follows: ztz yif iv - Air security:
Java
the biggest problem isnull
. If there is nonull
judgment on variables or parameters, a large number of them may be thrown in the programNullPointerException
, but these are difficult to detect during coding.Kotlin
Explicit is usednull
, which forces us to check if necessarynull
. - Syntactic sugar
- Simplification of classes, implicit getter(), setter()
- The default implementation of the interface
- lambdas and higher-order functions
- Null pointer safety, compile time null pointer checking
- Streaming collection operations map(), forEach()
- new features
- Function expansion, attribute expansion
- attribute proxy
Kotlin lightweight development
Null safe
Kotlin
is null
safe. If a type may be null
, then we need to add one after the type ?
. This way, we need to check every time a variable of this type is used null
. For example, the following code will not compile:
var artist: Artist? = null?
artist.print()
Line 2 will show an error because the variable is not null
checked. We can do this:
if (artist != null) {
? artist.print()?
}
This demonstrates Kotlin
another great feature: smart type conversion. If the variable's type is checked, there is no need to cast it in the checking scope. With this, we can now use variables as types if
in . This is true for other inspections as well. There is an easier way to check , which is to use it before calling the object's function . You can even provide an alternative approach via operators :artist
Artist
null
?
Elvis
?
val name = artist?.name ?: ""
data class data
In Java
, if we want to create a data class or POJO
a class (a class that just saves some state), we need to create a class with a lot of fields, getters
and setters
, and maybe provide toString
and equals
methods:
public class Artist {
private long id;
private String name;
private String url;
private String mbid;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMbid() {
return mbid;
}
public void setMbid(String mbid) {
this.mbid = mbid;
}
@Override public String toString() {
return "Artist{
" +
"id=" + id +
", name='" + name + '\'' +
", url='" + url + '\'' +
", mbid='" + mbid + '\'' +
'}';
}
}
In Kotlin
, the above code can be written as follows:
data class Artist (?
var id: Long,
var name: String,
var url: String,
var mbid: String)
Kotlin
Use properties instead of fields. Basically, a property is a field plus its getter
AND setter
.
Interoperability
Kotlin
Provides some great interoperability features, which are Android
very helpful for development. lambda
One of them is the mapping between an interface with a single method and an expression. Thus, the following click listener:
view.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View) {
toast("Click")?
}
?})
It can be written like this:
view.setOnClickListener {
toast("Click") }
Additionally, getters
and setters
are automatically mapped to properties. There is no performance penalty because the bytecode actually just calls the original getters
AND setters
. As shown in the following code:
supportActionBar.title = title
textView.text = title
contactsList.adapter = ContactsYifAdapter()
lambda expression
Lambda
Expressions will simplify the code to a great extent, but the important thing is that with the help of Lambda
expressions, we can do things that were previously impossible or very troublesome to implement. Expressions allow Lambda
us to think about problems in a more functional way. Lambda
An expression is actually a specified type, and the type defines a function. For example, we can define a variable like this:
val listener: (View) -> Boolean
This variable can declare a function that takes a view
and returns this function. We need to define the behavior of the function through closure:
val listener = {
view: View -> view is TextView }
The above function will receive an instance of View
, and if it view
is TextView
, it will return it true
. Since the compiler can infer the type, we don't need to specify it. It can also be more explicit:
val listener: (View) -> Boolean = {
view -> view is TextView }
With the help of Lambda
expressions, we can abandon the use of callback interfaces. Just set the function you want to be called later:
fun asyncOperation(value: Int, callback: (Boolean) -> Unit) {
...
callback(true)?
}
asyncOperation(5) {
result -> println("result: $result") }
There is a more concise way. If the function only receives one parameter, you can use reserved words it
:
asyncOperation(5) {
println("result: $it") }
higher order function
lambda`本身作为一等公民,它是有类型的。比如下面这个加法表达式sum的类型为`(Int, Int) -> Int。
val sum: (Int, Int) -> Int = { x, y -> x+y }
It is natural for a variable to have a type. Since the input and return value of a high-order function is lambda
, it is normal for its type to be a bit strange.
fun main(args: Array<String>) {
// 自定义高阶函数, lambda 表达式 作为入参
listOf("1", "2", "3", "4").myForEach {
println(it) }
// 自定义高阶函数, lambda 表达式 作为返回值
// getLogger()("I'm a Closure")
var logger = getLogger()
logger("I'm a Closure")
}
/**
* 接受一个 lambda 表达式, 作为遍历任务
*/
fun <T> List<T>.myForEach(doTask: (T) -> Unit){
for(item in this)
doTask(item)
}
/**
* 返回一个 lambda 表达式(闭包), 如: 日志输出工具 logger
*/
fun getLogger(): (String) -> Unit{
// return { println(it) }
return fun (it: String){
println(it)
}
}
PS: Seeing getLogger()
this usage, you probably realize that you can js
write closures like that.
The default implementation of the interface
As the name suggests, it means that the interface can have a default implementation of the method body like an abstract class. I attribute it to syntactic sugar, because there java8
is already exactly the same thing in China, and the corresponding keyword is called default
.
interface A {
fun foo() {
println("A") } // 默认实现, 打印"A"
fun bar()
}
interface B {
fun foo() {
println("B") }
fun bar() {
println("bar") }
}
// 多继承时,显式指定 super<A>.foo() 以去冲突
class D : A, B {
override fun foo() {
super<A>.foo()
super<B>.foo()
}
override fun bar() {
super.bar()
}
}
Streaming collection operations map(), forEach()
Streaming set operators are very common and can be found in any language. However, if they do not support functional expressions, they will be cumbersome to write. In the following example, the connection of some operators makes the operation logic very clear. If the demand changes later, such as changing descending order to ascending order, only one sortedDescending()
line needs to be changed, which is very flexible.
fun main(args: Array<String>){
val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
list.filter {
it%2==0 } // 取偶数
.map{
it*it } // 平方
.sortedDescending() // 降序排序
.take(3) // 取前 3 个
.forEach {
println(it) } // 遍历, 打印
}
// 输出:
100
64
36
expand
Expanding this thing seems to be done in the decorator mode. Its effect is to add functions without changing the source code. For example, if we want to Activity
add one toast()
, we don't need to uninstall the base class at all. This simplifies a lot of work, especially for some packaged jar
classes.
fun Activity.toast(msg: String) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
}
/**
* @author yif
*
* 函数拓展, 属性拓展
*/
fun main(args: Array<String>) {
val list = listOf("1", "2", "3", "4")
// 函数拓展
list.myForEach {
println(it) }
// 属性拓展
println("last: ${
list.lastItem}")
}
/**
* 拓展 List 类, 加一个自定义的遍历方法
*/
fun <T> List<T>.myForEach(doTask: (T) -> Unit){
for(item in this)
doTask(item)
}
/**
* 拓展 List 类, 加一个自定义的长度属性
*/
val <T> List<T>.lastItem: T
get() = get(size - 1)
// 输出:
1
2
3
4
last: 4
attribute proxy
It delegates the properties of get()
the set()
property to a class so that it can do some additional operations during get()
and . set()
like:
- Lazy loading
- Observer (automatically notifies when properties change)
- Taking lazy loading as an example for attribute non-empty judgment,
lazySum
it may require complex operations, so we delegate it tolazy
. As you can see, only the first load is calculated, and subsequent values are taken directly, which improves efficiency. val lazySum: Int by lazy { println("begin compute lazySum ...") var sum = 0 for (i in 0…100) sum += i println("lazySum computed!n") sum // Return the calculation result} fun main (args: Array<String>) { println(lazySum) println(lazySum) } // Output: begin compute lazySum … lazySum computed! 5050 5050 AnkoAnko
isKotlin
a library developed by the team to simplifyAndroid
development. Its main goal is to provide a viewDSL
that can be declared usingKotlin
code: verticalLayout { val name = editText() button("Say Hello") { onClick { toast("Hello, ${name.text}!") } } } It also Provides some other useful features. For example, navigate to otherActivity
And pass values to other interfaces: startActivity("id" to res.id, "name" to res.name) startActivity<ContentActivity>( Pair(Constants.CONTENT_TITLE_KEY, useWebsiteBean.name), Pair(Constants.CONTENT_URL_KEY, useWebsiteBean.link ), Pair(Constants.CONTENT_ID_KEY, useWebsiteBean.id) ) Summary Kotlin really simplifies Android development work in many aspects. It will increase your productivity and solve some common problems in a very different and simpler way. Let’s use Kotlin for rapid and agile development .