BuglyThe contents of the technical dry goods series are mainly related to the direction of mobile development. They are written by Bugly inviting all the technical masters in Tencent through the summary and perception of daily work experience. The contents are original, please indicate the source if you reprint them.
1.1 Kotlin’s History
-
After writing Java for a long time, have you noticed that you are writing too much redundant code?
-
Later, when you tried Python, did it feel super cool not to write semicolons?
-
Aren’t you tired of working hard and being tortured by Nullpointerexceptions?
-
Until one day you’ve written hundreds of thousands of lines of code and it’s all getters and setters!
In fact, you can use Kotlin instead of Java to develop your applications, whether Android or Server, you will be able to think like Java before, while enjoying the features of the new generation of programming language. I’m going to use this article to tell you who Kotlin is.
Kotlin, by the way, is a statically typed language that runs on the JVM from JetBrain and is named after an island in the Baltic Sea. I was thinking about Scala as my next language, but think about what to do with Scala. I don’t do big data, and it’s just too complicated
Scala plain text view copy code
data class Mondai(var index: Int = 0,
var title: String = "",
val ans: ArrayList = ArrayList(),
var correct: Int = 0,
var comment: String = "",
var color: String = "",
private var lives: Int = 50)Copy the code
Kotlin’s extensions to Android have been added, as well as Kotlin’s Gradle plugin.
I first saw Kotlin in the intelliJ source code. At that time, the Kotlin version was not stable, so the source code was compiled all the time. By the way, Kotlin, does that mean “by its spirit”?
In fact, after more than a year of development, Kotlin 1.0 has been released, the feature has been basically improved, and the API tends to be stable. At this time, there will not be that kind of pit feeling when trying. During the Spring Festival, I was also free, so I made an app with Kotlin, which, in a nutshell, has several feelings:
- The idea is the same as writing Java, but cleaner and cleaner
- With less redundant code, it is easier to focus on the development of features and the whole process is relaxed and enjoyable
- Extensions make code more fun to write
- Null-safe and immutable types have led to a greater focus on variable definition and initialization in development
- Oh, I don’t have to write findViewById anymore.
1.2 The first Kotlin program
Of course, the JetBrain series of ides are used for Kotlin development. In fact, intelliJ Idea 15 came with the Kotlin plugin built in, Earlier versions require you to download and install the Kotlin plugin from the plugin repository — you’ll also see the Kotlin Extensions for Android at the time of installation, which is outdated anyway. Once installed, we are ready to use Kotlin for development.
[Groovy] Plain text view copy code
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' ext.anko_version = '0.8.2' ext.kotlin_version = '1.0.0'...... Dependencies {... compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" compile "org.jetbrains.anko:anko-sdk15:$anko_version" compile "org.jetbrains.anko:anko-support-v4:$anko_version" compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" ... } buildscript { repositories { jcenter() } dependencies { classpath "Org. Jetbrains. Kotlin: kotlin - gradle - plugin: $kotlin_version"}}...Copy the code
Now you can write the Kotlin code — wait, Android Studio will generate a MainActivity for us, which you can use directly in the menu
Code -> Convert Java file to Kotlin file
Convert this Java code to Kotlin code. As of now, you don’t have to do anything, and the program is already running.
2. Perfect for Java developers
2.1 General collection framework
We all know that languages on the Jvm, such as Java, Groovy, Jython, etc., are coded into the virtual machine’s bytecode, and once coded, everyone is equal to a certain extent.
Heroes don’t know where they came from
Someone has made a very vivid analogy: Java virtual machine language is fighting. Kotlin takes full advantage of this, its own standard library is just a lot of extensions to the Java-based language framework, and the collections framework you use in Kotlin is still the same as it is in Java.
Scala plain text view copy code
Val list = arrayListOf(1,2,3,4) list.add(5) list.remove(3) for(item in list){println(item)} val list = arrayListOf(1,2,3,4) list.add(5) list.remove(3) {println(item)}Copy the code
Scala plain text view copy code
val list = arrayListOf(1, 2, 3, 4, 5) //doubleList = [2,4,6,8,10] val doubleList = list.map {it * 2} //oddList = [1,3,5] val oddList = list.filter{it % List. ForEach {println(it)}Copy the code
2.2 Interaction with Java
Kotlin’s standard library is more of an extension of the Java library. With this in mind, you don’t need to worry about Kotlin referencing Java code. You can even use Java reflection in Kotlin.
Kotlin is an extension of Java
It’s obviously unfair to say that about Kotlin, but it’s like getting offline messages for QQ when wechat was first launched.
Prepare a Java class
[Java] Plain text view copy code
public class JavaClass { private int anInt = 0; public int getAnInt() { return anInt; } public void setAnInt(int anInt) { this.anInt = anInt; }}Copy the code
Scala plain text view copy code
val javaClass = JavaClass()
javaClass.anInt = 5
print(javaClass.anInt)Copy the code
Scala plain text view copy code
view.background = ...
textView.text = ...Copy the code
3. Be concise, reliable, and fun
3.1 data classes
When I first learned Java, I was tortured by a concept called JavaBean. A simple thing turned out to be very complicated, and since the design concept of these data classes was not very clear at that time, I did not know how to override important methods such as equals and Hashcode. Once I used the collection framework such as HashMap, I always had problems and did not know who to call.
Scala plain text view copy code
data class Coordinate(val x: Double, val y: Double)Copy the code
With just one line of code, Kotlin creates a complete data class and automatically generates the corresponding equals, HashCode, and toString methods. Have you had enough of getters and setters? I’ve had enough of it anyway.
3.2 Air security and attribute proxy
When I first saw null-type safety in Swift, I thought it was a bit interesting. Once a variable can’t be null, the possibility of null-pointer exceptions goes away. Think about every time QA mentions a bug, 1/3 of it is null.
Kotlin’s air safety design, mainly after the type? Indicates nullable, otherwise cannot be null.
Scala plain text view copy code
// error val anotherInt: Int? = null // CorrectCopy the code
When used, then:
Scala plain text view copy code
val nullable: Int? = 0 val nonNullable: Int = 2 nullable. ToFloat () .toFloat() // If null, do nothing, otherwise call toFloat nullable!! .tofloat () // cast to a non-empty object and call toFloat; If nullable is null, the nullable exception nonnullable.tofloat () // is correctCopy the code
For Java code, for example, we override the Activity’s onCreate method with the savedInstanceState parameter:
Scala plain text view copy code
override fun onCreate(savedInstanceState: Bundle!) Copy the code
This means that the compiler no longer enforces the nullability of savedInstanceState, and developers can decide whether to nullability savedInstanceState when overwriting. Of course, for this example, the onCreate argument may be null, so the overwrite method should be:
Scala plain text view copy code
override fun onCreate(savedInstanceState: Bundle?)Copy the code
Normally, this is the end of the textbook argument. However, it wasn’t until I actually started coding with Kotlin that I realized that some of the requirements were really strange to implement.
For example, I need to create a reference to a View in my Activity, usually in Java code:
[Java] Plain text view copy code
public class DemoActivity extends Activity{ private TextView aTextView; public void onCreate(Bundle savedInstanceState){ super.OnCreate(savedInstanceState); setContentView(R.layout.main); aTextView = (TextView) findViewById(R.id.a_textview); aTextView.setText("Hello"); aTextView.setTextSize(20); . }}Copy the code
In Kotlin?
Scala plain text view copy code
class DemoActivity : Activity(){ private var aTextView: TextView? = null override fun onCreate(savedInstanceState: Bundle?) {super.oncreate (savedInstanceState) setContentView(r.layout.main) ATextView = findViewById(R.i.a.textView) as TextView aTextView!! .text = "Hello" aTextView!! .textSize = 20 ... }}Copy the code
Every time I use aTextView, I add two! Otherwise, the compiler cannot determine whether it is null and will not let you use it. What the fuck… Is it for convenience or trouble?
So I decided to write it this way:
Scala plain text view copy code
Class DemoActivity: Activity(){private var aTextView: TextView // compiler error, must initialize!! . }Copy the code
} “” what can be done?
Kotlin definitely has a solution to this problem. For example, in the above scenario, we can write it like this:
Scala plain text view copy code
class DemoActivity : Activity(){
private val aTextView: TextView by lazy{
findViewById(R.id.a_textview) as TextView
}
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
aTextView.text = "Hello"
aTextView.textSize = 20
...
}
}Copy the code
Lazy is an instance of Kotlin’s property broker, which provides a lazy loading mechanism. In other words, lazy provides a way to initialize the aTextView, but the actual initialization happens when the aTextView is first used. Lazy is thread-safe by default. You can also turn lazy off by adding a parameter:
Scala plain text view copy code
private val aTextView: TextView by lazy(LazyThreadSafetyMode.NONE){
findViewById(R.id.a_textview) as TextView
}Copy the code
Lazy initialization: val = null, val = null, val = null, val = null, val = null
Scala plain text view copy code
class Demo { lateinit var anJsonObject: JsonObject fun initDemo(){ anJsonObject = JsonObject("{... }}} ")Copy the code
There are some limitations to using LateInit. It can only be used on non-null objects (var, primitives, etc.), but forcing you to initialize lateInit reduces omissions and improves development efficiency.
The lazy technique is actually an application of Delegate Properties, or property proxies. In Kotlin, member attributes can be declared as a Delegate in addition to being assigned directly. The Delegate needs to provide the corresponding getValue and setValue methods based on the member’s type (val or var), such as a read-write Delegate. The following methods need to be provided:
[Groovy] Plain text view copy code
public interface ReadWriteProperty {
/**
* Returns the value of the property for the given object.
* @param thisRef the object for which the value is requested.
* @param property the metadata for the property.
* @return the property value.
*/
public operator fun getValue(thisRef: R, property: KProperty<*>): T
/**
* Sets the value of the property for the given object.
* @param thisRef the object for which the value is requested.
* @param property the metadata for the property.
* @param value the value to set.
*/
public operator fun setValue(thisRef: R, property: KProperty<*>, value: T)
}Copy the code
Let’s take a look at a custom Delegate that accesses SharedPreference:
Scala plain text view copy code
class Preference(val context: Context, val name: String, val default: T) : ReadWriteProperty { val prefs by lazy { context.getSharedPreferences("default", Context.MODE_PRIVATE) } override fun getValue(thisRef: Any? , property: KProperty<*>): T { return findPreference(name, default) } override fun setValue(thisRef: Any? , property: KProperty<*>, value: T) { putPreference(name, value) } private fun findPreference(name: String, default: U): U = with(prefs) { val res: Any = when (default) { is Long -> getLong(name, default) is String -> getString(name, default) is Int -> getInt(name, default) is Boolean -> getBoolean(name, default) is Float -> getFloat(name, default) else -> throw IllegalArgumentException("This type can be saved into Preferences") } res as U } private fun putPreference(name: String, value: U) = with(prefs.edit()) { when (value) { is Long -> putLong(name, value) is String -> putString(name, value) is Int -> putInt(name, value) is Boolean -> putBoolean(name, value) is Float -> putFloat(name, value) else -> throw IllegalArgumentException("This type can be saved into Preferences") }.apply() } }Copy the code
To be clear, I took this code from the Kotlin for Android Developer example. With the Delegate class, we don’t need to care about SharedPreference at all. Here’s some sample code to use:
Scala plain text view copy code
class WhateverActivity : Activity(){ var aInt: Int by Preference(this, "aInt", 0) fun whatever(){println(aInt) {aInt = 9 // SharedPreference}}Copy the code
So we don’t have to write getShare Preference again, edit, commit, and forget commit days after edit. Do you think it’s awesome?
3.3 extensions class
Extension class, is on the basis of the existing class, add some attributes or methods, of course, these extended members need to import the current extension members of the package can be accessed. Here’s an example:
Scala plain text view copy code
data class Coordinate(val x: Double, val y: Double)
val Coordinate.theta: Double
get() {
return Math.atan(y/x)
}
fun Coordinate.R():Double{
return Math.hypot(x, y)
}Copy the code
We’ve already introduced data class Coordinate which has two members x and y, and we know that it’s usually a two-dimensional plane, and that’s enough; However, we often need to figure out polar coordinates in graphics, so we extended Coordinate, adding a property theta to indicate the Angle (the arc tangent is in the range of -π/2 to π/2, so it doesn’t work in the second and third quadrants, but that’s not the point), adding an R method to get the radius of the point, So we can use this in the main method:
Scala plain text view copy code
Fun main(args: Array) {val coord = Coordinate(3.0,4.0) println(coord.theta) println(coord.r ())}Copy the code
So what are the limitations of this extension?
- Within extended members, only members of the extended class that are visible in the current scope can be accessed. In this case, both x and y are public (Kotlin defaults to public, which we’ll mention later), so they can be accessed directly in extension methods and properties.
- If the extended member has the same name as the inner member of the extended class, the extended member cannot be accessed
Ok, so that’s the basics, but let’s do a real example.
Log.d is a tag, and sometimes the class doesn’t even have a tag. In practice we usually use the current class name as a TAG, but it’s not fun to do this for each class (I used LiveTemplates to help me, and even then it didn’t feel that smooth).
Life is much easier with this extension from Kotlin. Here’s a method I created to log:
Scala plain text view copy code
package com.benny.utils
import android.util.Log
inline fun T.debug(log: Any){
Log.d(T::class.simpleName, log.toString())
}Copy the code
With this method, you can write in the body of any class directly:
Scala plain text view copy code
debug(whatever)Copy the code
The log with the class name TAG is then printed.
Well, here’s a quick look at one of Kotlin’s more important enhancements to generics that you can’t do in Java anyway: inline, reified. If we go back to the debug method, we see that it can use the generic parameter T to get the specific type of T and get its class name – of course, you can even call its constructor to construct an object if you want – why Kotlin can do that? Because this code is inline, the type of T is actually fixed when it is compiled into the calling block. Kotlin uses the reified keyword to tell the compiler that T is not just a trick but that I want to use it as the actual type.
In order to impress you, I give the following Java code implementation of similar functions:
[Java] Plain text view copy code
public static void debug(Class clazz, Object log){
Log.d(clazz.getSimpleName(), log.toString());
}Copy the code
If you want to get the type of the generic parameter in Java, you can’t:
[Java] Plain text view copy code
public static void debug(Object log){ Log.d(T.getSimpleName(), log.toString()); // error, T is a generic parameter, cannot be used directly}Copy the code
Even if we write debug < Date >(“blabla”) on the call, the Date will be erased after compilation.
3.4 Functional Support (Lambdas)
Java 8 already has support for Lambda expressions, something that might seem a bit unnatural for Java, a red-hot object-oriented programming language, but Kotlin doesn’t have much to worry about.
Usually we need to execute a bit of asynchronous code. We construct a Runnable object and hand it to the executor, such as this Java code:
[Java] Plain text view copy code
executor.submit(new Runnable(){
@Override
public void run(){
//todo
}
});Copy the code
How do I write it in Kotlin?
Scala plain text view copy code
executor.submit({
//todo
})Copy the code
It saves a lot of code.
In practice, we may see the following example more often. This is a very common Piece of Java code that is seen in Android UI initialization:
[Java] Plain text view copy code
textView.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view){
//todo
}
});
handle.post(new Runnable(){
@Override
public void run(){
//todo
}
});Copy the code
So what do we write in Kotlin?
Scala plain text view copy code
textView.setOnClickListener{ /*todo*/ }
handler.post{ /*todo*/ }Copy the code
With the help of Anko, the Android library, we can even simplify the OnClickListener setup:
Scala plain text view copy code
textView.onClick{ /*todo*/ }Copy the code
Of course, there’s more to it than that. If you combine the extension methods we mentioned in the previous section, it’s easy to see how methods like with and Apply provided by Kotlin’s library work:
Scala plain text view copy code
public inline fun with(receiver: T, block: T.() -> R): R = receiver.block()
public inline fun T.apply(block: T.() -> Unit): T { block(); return this }Copy the code
We normally create an object inside a method body and return it, but we need to do something other than call its constructor, so we create a local variable… With the apply extension, we can write:
Scala plain text view copy code
fun getStringBuilder: StringBuilder{
return StringBuilder().apply{
append("whatever")
}
}Copy the code
This returns a StringBuilder object that actually contains the string “whatever”.
As for Kotlin’s RxJava friendliness, I suddenly have a little faith in serendipity:
Scala plain text view copy code
Observable.create> { it.onStart() try { it.onNext(dummyObjs) } catch(e: Exception) { it.onError(e) } finally { it.onCompleted() } }.subscribe(object : Subscriber>() { override fun onCompleted() { } override fun onNext(t: ArrayList?) { } override fun onError(e: Throwable?) {}})Copy the code
3.5 the Pattern Matching
Remember when I was browsing Scala’s features and saw:
Scala plain text view copy code
object HelloScala{
// do something
}Copy the code
A friend said that Scala’s pattern matching is really sharp — Kotlin also has this feature. Here’s an example:
Scala plain text view copy code
val x = 7 when (x) { in 1.. 10 -> print("x is in the range") in validNumbers -> print("x is valid") ! in 10.. 20 -> print("x is outside the range") else -> print("none of the above") }Copy the code
At first glance, the when expression looks like an enhanced version of the Switch — the previous Switch in Java 7 actually supported very limited types, and the added String support in Java 7 was based on ints — we can see that when no longer matches only one value, as switch does. Its subexpressions can be various expressions that return Boolean.
There is a more revolutionary way to write the when expression:
Scala plain text view copy code
when {
x.isOdd() -> print("x is odd")
x.isEven() -> print("x is even")
else -> print("x is funny")
}Copy the code
Any expression that returns Boolean can be used as a subexpression of WHEN, which shows the flexibility of the WHEN expression. Of course, compared to Scala,
Kotlin is a little more conservative, and here’s a similar example in Scala that actually shows Kotlin’s philosophy of keeping things simple while adding Java(As you all know, Scala requires INTELLIGENCE, after all.
Scala plain text view copy code
object Hello { def main(args: Array[String]) {easyMatch((1, 3)) easyMatch(Array(1,3)) easyMatch(Bean(3.0, 4.0))} def easyMatch(value: Any) = value match { case int :Int => { println("This is an Int.") } case (a, b) =>{ println(s"a tuple with : $a , $b") } case Bean(x, y) => { println(s"$x, $y") } case whatever => println(whatever) } } case class Bean(val x: Double, val y: Double)Copy the code
The running results are as follows:
[Bash shell] Plain text view copy code
A tuple with: 1, 3 [I@2d554825 3.0, 4.0Copy the code
3.6 If you are an SDK developer
I’ve been working on AN SDK for a while. There are a lot of classes in the SDK that actually need to have access to each other, but once classes and their members are public, callers can see them. Visibility such as protected or default is not visible to subpackages.
After working with Java for so long, this is really the only thing I have a strong complaint about, even though I suddenly understand how useful C++ friend can be.
Kotlin does not provide a modifier visible to subpackages, but it does provide internal: visible within a module. In other words, internal is public inside a module and private outside of it — so if we develop an SDK, we can reduce the API layer and use internal for the parts that aren’t visible to the user. Of course some people would say that we should have proGuard for confusion. I would say that proGuard is certainly going to be used, but that’s the next step in the SDK product process. Why can’t we do this at the code level?
3.7 the DSL
Gradle scripts are DSLS based on Groovy, and Kotlin’s functions support DSLS as well. For example, we end up generating the following XML data:
[XML] Plain text view copy code
Copy the code
We can build the following classes:
Scala plain text view copy code
class Project {
var version: String? = null
get() =
if (field == null) ""
else {
" version=\"${field}\""
}
lateinit private var component: Component
fun component(op: Component.() -> Unit) {
component = Component().apply {
op()
}
}
override fun toString(): String {
return "${component}"
}
}
fun project(op: Project.() -> Unit): Project {
return Project().apply {
op()
}
}
class Component {
var name: String? = null
get() =
if (field == null) ""
else {
" name=\"${field}\""
}
lateinit private var file: File
fun file(op: File.() -> Unit) {
file = File().apply {
op()
}
}
override fun toString(): String {
return "${file}"
}
}
class File {
var url: String? = null
get() =
if (field == null) ""
else {
" url=\"${field}\""
}
var charset: String? = null
get() =
if (field == null) ""
else {
" charset=\"${field}\""
}
override fun toString(): String {
return ""
}
}
fun main(args: Array) {
val xml = project {
version = "4"
component {
name = "Encoding"
file {
url = "PROJECT"
charset = "UTF-8"
}
}
}
println(xml)
}Copy the code
We can see that in the main method, we write a Project object using the DSL defined by Kotlin, which has the same structure and meaning as the XML description. If you like, you can construct the corresponding method to output such XML, and run the result:
[XML] Plain text view copy code
Copy the code
Of course, this example is crude enough that you can abstract away “Element” and add “Attributes” if you’re interested, which isn’t too hard.
3.7 Other interesting things about Kotlin and Android
It’s frustrating to write a lot of code only to find that it doesn’t do much. For example, one of the things I’ve been struggling with is:
[Java] Plain text view copy code
Button button = (Button) findViewById(R.id.btn);Copy the code
If I need a lot of buttons and images, we’ll write a whole bunch of findViewById like this. Oh, my… I can’t do this job.
But with Kotlin’s Android extension, we can do this:
Layout file first:
main.xml
[XML] Plain text view copy code
Copy the code
Copy the code
In the Activity:
Scala plain text view copy code
Package com. Benny... import kotlinx.android.synthetic.main.load_activity.* import org.jetbrains.anko.onClick import . Org. Jetbrains. Anko startActivity import org. Jetbrains. Anko. Toast... class LoadActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) {super.oncreate (savedInstanceState) setContentView(r.layout.main) start.onClick {toast(" start ") startActivity()} Textview.text = "Hello"}}Copy the code
Notice:
Scala plain text view copy code
import kotlinx.android.synthetic.main.load_activity.*Copy the code
After importing this sentence, we can use start and textView directly in our code, which correspond to the button with id start in main.xml and the textView with ID textView, respectively.
You’ll never have to use findViewById again!! Of course, you’ll also find it easier to call Toast, which is essentially an extension method Toast (); StartActivity, on the other hand, is an inline plus reified application, which we’ve already mentioned.
Another disgusting thing is the problem of switching between UI threads and non-UI threads. Handler is a very powerful tool that can be used to post a lot of code, but it is a very powerful tool that can be used to post a lot of code.
In Java, we write:
[Java] Plain text view copy code
handler.post(new Runnable(){
@Override
public void run(){
//todo
}
});
MainActivity.this.runOnUiThread(
public void run(){
//todo
}
});Copy the code
In Kotlin, we just write:
Scala plain text view copy code
async() {
//do something asynchronously
uiThread {
//do something on UI thread
}
}Copy the code
Feel it for yourself.
Another interesting thing to mention is that we had to write XML from the beginning of Android development, which I remember was a real pain in the ass because it didn’t work as directly as code (so much so that I now prefer to write layouts directly in Java code) — of course, The main problem is not that, but that parsing XML is cpu-intensive. Kotlin has a solution to this problem: DSLS. Here’s an example:
Scala plain text view copy code
linearLayout {
button("Login") {
textSize = 26f
}.lparams(width = wrapContent) {
horizontalMargin = dip(5)
topMargin = dip(10)
}
}Copy the code
A LinearLayout contains a Button that you can write directly into your code and reuse flexibly, like this:
Scala plain text view copy code
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(linearLayout { button("This is a button") { onClick { toast("clicked!" ) } }.lparams { width = matchParent verticalMargin = dip(5) } }) }Copy the code
There are many advantages to this:
- This is much cleaner than XML
- The layout itself is code that can be reused
- Don’t you think you’ve wasted enough life on findViewById
- Event listeners are easily embedded in the layout
- Dsl-style layout without the burden of runtime parsing, does your logic code run the way it does
- Anko also adds more fun features for those interested: Anko@Github
3.8 Method number pain
I tried to write HelloWorld for Android in Scala, and after everything was configured, I introduced only a few common Scala libraries, plus common ones like support-V4 and AppCompat, and still got an error. Yes, 65K… And when developing Android in Scala, building on Gradle makes the entire app build process extremely long. Sometimes you feel like you’ve figured out the meaning of general relativity. Oh no, you must be confused.
Kotlin’s standard library, by comparison, has only 7,000 methods, smaller than support-V4, reflecting Kotlin’s design philosophy of 100% Interoperable with Java. In fact, as we mentioned earlier, Java has Kotlin to use directly, while Scala’s standard library has more than 50 million methods, so think about it.
4, summary
There’s something romantic about being adventurous, and we programmers can be romantic, but in a generative environment, stability is still the rule. Pursuing new technologies, on the one hand, imposes learning costs on the team in terms of development and maintenance, and on the other hand, risks unknown problems in future situations due to unfamiliarity with the new technology — nothing bosses fear more than risk
With this in mind, there is no doubt that Kotlin can be used as a development tool for widgets, test cases, and so on, given that this code is typically small in size, maintained by fewer people, concentrated, and has less impact on the project as a whole; For core code, it depends.
Personally, Kotlin will most likely become my main language in the long run, while in the short term it will continue to trickle in with mild reforms.
Kotlin is meant to be efficient, and if it’s not, or even a drag in your scenario, let it go.