Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Why not use Java's grammatical thinking to write Kotlin

2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly explains "Why do not use the grammatical thinking of Java to write Kotlin", the content of the explanation is simple and clear, easy to learn and understand, the following please follow the editor's train of thought slowly in depth, together to study and learn "Why not use the grammatical thinking of Java to write Kotlin"!

1. Use as little as possible!

Personally, I feel that checking Null is the most grammatical sugar of Koltin, forcing null pointers to be considered in the coding process, so "billion-dollar mistake", you may not have the chance to make a mistake again (maybe you made a billion dollars ^ _ ^).

First of all, we need to introduce you! Operator.

!! Operator: this is for null pointer lovers, the non-null breaker operator (!) Converts any value to a non-null type, and throws an exception if the value is empty. We can write a null!, which returns a non-empty a value (for example, String in our example) or throws a null pointer exception if an is empty:

Val b = a minimum length.

So, we don't have to! Do not use the operator.

Here are several ways to avoid using it! Operator

1)。 Use val instead of var

In Kotlin, val stands for read-only and var stands for variable. It is recommended that you use val as much as possible. Val is thread-safe and must be initialized at definition time, so there is no need to worry about null. Just note that val is mutable in some cases.

Val and var are used to indicate whether an attribute has a getter/setter:

Var: both getter and setter

Val: only getter

Therefore, it is highly recommended to use val where val can be used.

2)。 Use lateinit

Sometimes val cannot be used, for example, val cannot be used in spring boot interface testing, in which case the lateinit keyword can be used.

Depending on inversion, the object is created through spring, while val requires initialization when it is defined.

/ * * Created by quanke on 2018-1-9. * Site: http://woquanke.com. * / @ RunWith (SpringRunner::class) @ SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class ApplicationTests {val log = LogFactory.getLog (ApplicationTests::class.java)! @ Autowired lateinit var restTemplate: TestRestTemplate @ Test fun `GET when given quanke then returns "Hello, quanke" `() {/ / Given val name = "quanke" / / When val body = restTemplate.getForObject ("/ users/hello/ {name}" String::class.java, name) / / Then assertThat (body) .isEqualTo ("Hello, $name")}}

Note: lateinit is easy to use, but there are also holes.

Accessing an uninitialized lateinit property results in UninitializedPropertyAccessException.

Lateinit does not support basic data types, such as Int. For basic data types, we can do this:

> private var mNumber: Int by Delegates.notNull () >

3) .Elvis operator

When b is a nullable reference, we can use if expressions to handle the

Val l: Int = if (b! = null) b.length else-1

But a more elegant way is to use the Elvis operator?

Val l = b?.length?:-1

If the left expression is not empty, the elvis operator returns its left expression, otherwise it returns the right expression.

Note: the right expression is evaluated only if and only if the left side is empty.

4)。 Maybe you can try the let function.

The let function is generally used with the security call operator, so let's first introduce the security call operation?.

B?.length

If b is not empty, b.length is returned, otherwise null is returned, and the type of this expression is Int?

Secure calls are useful in chained calls. For example, if an employee Quanke may (or will not) be assigned to a department, and another employee may be the head of that department, then get the name of the head of the department where Quanke is located, if any, and we write:

Quanke?.department?.head?.name

If any of the attributes (links) are empty, the chained call returns null.

If you want to perform an operation on only non-null values, the security call operator can be used with let:

Val listWithNulls: List = listOf ("A", null) for (item in listWithNulls) {item?.let {println (it)} / / output An and ignore null}

There is also a common mistake (try it in ide and you'll see what's wrong):

Private var a: String? = null fun aLetDemo () {if (a! = null) {test (a)}}

We can do this:

Private var a: String? = null fun aLetDemo () {if (a! = null) {test (a!)}}

But the consequence is that you still need to deal with null pointers in the test function.

We make full use of?. Add the features of let to solve this compilation error more elegantly, as follows

Private var a: String? = null fun aLetDemo () {if (a! = null) {a?.let {test (it)}

two。 Write less about Util classes and inheritance

Most of the time, the method provided to me by the framework is to compare atoms, or some common method frameworks are not provided. Java usually writes a utility class:

Public final class StringUtil {/ * remove all punctuation characters * * @ param str processed string * / public static String trimPunct (String str) {if (isEmpty (str)) {return ";} return str.replaceAll (" [\ pP\\ p {Punct}] ",");}}

Kotlin can be implemented in the form of extension functions:

/ * * remove all punctuation strings processed by * * @ param str * / fun String.trimPunct (): String {return if (this.isEmpty ()) {"} else this.replace (" [\\ pP\\ p {Punct}] ".toRegex (),")}

Call:

Fun main (args: Array) {val a = "get rid of my punctuation, general practice." Print (a.trimPunct ())}

Print:

Get rid of my punctuation. General practice Process finished with exit code 0

3. Stop concatenating strings with the + sign

Whether it is Java or Android development, we will use string concatenation, such as log output and so on. In Kotlin, string templates are supported, and we can easily concatenate a number of strings. Of course, you might say that it is better to use StringBuilder, such as:

Val site = "http://woquanke.com" val sb: StringBuilder = StringBuilder () sb.append (" my blog name is'my general practitioner', and my blog address is: ") sb.append (site) println (sb.toString ())

But kotlin's string template can do this gracefully:

Val site = "http://woquanke.com" println (" my blog name is "my general practitioner" and my blog address is: $site)

4. Maybe we can forget getters/setters.

We often create classes that only hold data. In these classes, some standard functions are often generated by manipulating ide. In Kotlin, this is called a data class and marked as data:

Data class User (val name: String, val age: Int)

Methods of automatically generating getter,setting,hashcode and equals by data class

5. Please forget the ternary operator

In Kotlin, if is an expression, that is, it returns a value. So there is no need for ternary operators (conditions? Then: otherwise), because the ordinary if can be qualified for this role.

/ / as the expression val max = if (a > b) an else b

6. Where is the switch?

When replaces the switch operator of the java-like language. Its simplest form is as follows:

When (x) {1-> print ("x = = 1") 2-> print ("x = = 2") else-> {/ / Note this block print ("x is neither 1 nor 2")}}

If many branches need to be handled in the same way, you can put multiple branch conditions together and separate them with commas:

When (x) {0,1-> print ("x = = 0 or x = = 1") else-> print ("otherwise")}

You can use any expression (not just a constant) as a branching condition

When (x) {parseInt (s)-> print ("s encodes x") else-> print ("s does not encode x")}

You can also detect whether a value is in (in) or not in (! in) an interval or set:

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")}

Another possibility is to detect whether a value is (is) or not (! is) a specific type of value. Note: due to smart conversions, you can access this type of methods and properties without any additional detection.

Fun hasPrefix (x: Any) = when (x) {is String-> x.startsWith ("prefix") else-> false}

When can also be used to replace the if-else if chain. If no parameters are provided, all branch conditions are simple Boolean expressions, and when the condition of a branch is true, the branch is executed:

When {x.isOdd ()-> print ("x is odd") x.isEven ()-> print ("x is even") else-> print ("x is funny")}

7. Screw your ClassCastException.

Kotlin Intelligent Transformation (Smart Casts)

For immutable values, Kotlin generally does not need to explicitly convert object types, and the compiler can track is check types and automatically insert type conversion code when needed (safe):

Fun classCast (a: Any) {if (an is String) {print (a.length) / / Compiler automatically converts a to String type}}

The Kotlin compiler is smart enough to recognize reverse checking types! is operator, which automatically inserts type conversion code:

If (a! is String) return print (a.length) / / the compiler automatically converts x to String type: / / | on the right, an automatically converts to String type if (a! is String | | a.length = = 0) return / / & & right An automatically converted to String type if (an is String & & a.length > 0) {print (a.length) / / an automatically converted to string} / / Smart conversion (smart casts) is also used for when expressions and while loop when (a) {is Int-> print (a + 1) is String-> print (a.length + 1) is IntArray -> print (a.sum ())}

Smart conversions cannot be used if there is no guarantee that the variables are immutable between the type checking isUniverse operator and the variable usage. Applicable conditions or rules for intelligent transformation:

Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community

Val local variables-always apply!

Val attribute-applies to private or internal, or type checking is done in the same module where the attribute is declared

Does not apply to properties of open, or has properties of custom getter!

Var local variable-applies when the variable is not modified between type checking and use, and is not captured in the lambda that modified it!

Var property-not applicable (because this variable can be modified at any time)

Secure (nullable) conversion-operator as?

To avoid throwing an exception, you can use the secure conversion operator as?, which returns null on failure

Val a: String? = b as? String

Even though as? On the right is a non-empty type String, but as? Returns null when the conversion fails, in other words, as? The function argument String cannot be null, but as? The return value of a function can be null

8. You really have to get used to Koltin's for loop. It's too powerful.

Kotlin does not have the rule of for (initial value; condition; increase or decrease step size) in Java. However, other rules have been added to the for loop statement in Kotlin to satisfy the rules just mentioned.

Hongmeng official Strategic Cooperation to build HarmonyOS Technology Community

The for loop provides iterators for traversing anything.

The for loop array is compiled into an index-based loop, which does not create an iterator object

A new rule to satisfy the for (initial value; condition; increase or decrease step size) rule

Increment

Keyword: until

Range: until [n ·m) = >, that is, greater than or equal to n, less than m

Example:

/ / Increment for (I in 0 until 5) {print ("I = > $I\ t") with a step size of 1

The output is

I = > 0 I = > 1 I = > 2 I = > 3 I = > 4

Decreasing

Keyword: downTo

Range: downTo [n < m] = > that is less than or equal to n, greater than or equal to m, n > m

Example:

/ / decreasing for with a step size of 1 (I in 15 downTo 11) {print ("I = > $I\ t")}

The output is as follows:

I = > 15 I = > 14 I = > 13 I = > 12 I = > 11

Symbol ('. ') represents another operation of an incremental loop

Use symbols ('..').

Range:. [n ·m] = > that is greater than or equal to n, less than or equal to m

The difference with until is simplicity. The second is the difference in scope.

Example:

Print ("print result using symbol `..`\ n") for (I in 20.. 25) {print ("I = > $I\ t")} println () print ("print results using until\ n") for (I in 20 until 25) {print ("I = > $I\ t")}

The output is as follows:

Use symbols.. The printing result of

I = > 20 I = > 21 I = > 22 I = > 23 I = > 24 I = > 25

Print results using until

I = > 20 I = > 21 I = > 22 I = > 23 I = > 24

Set step size

Keyword: step

Example:

For (I in 10 until 16 step 2) {print ("I = > $I\ t")}

The output is as follows:

I = > 10 I = > 12 I = > 14

Iteration

The for loop provides an iterator for traversing anything.

The for loop array is compiled into an index-based loop, which does not create an iterator object

Traversal string

This usage has been used in string types in the data types section. For those who are not clear, you can check out the most detailed description of Kotlin-- 's data types.

Example:

For (I in "abcdefg") {print ("I = > $I\ t")}

The output is as follows:

I = > an I = > b I = > c I = > d I = > e I = > f I = > g

Ergodic array

This usage has been used in array types in the data types section. For those who are not clear, you can check out the most detailed description of Kotlin-- 's data types.

Example:

Var arrayListOne = arrayOf (10, 20, 30, 40, 50) for (i in arrayListOne) {print ("I = > $I\ t")}

The output is as follows:

I = > 10 I = > 20 I = > 30 I = > 40 I = > 50

Traversing using the indices property of the array

Example:

Var arrayListTwo = arrayOf for (I in arrayListTwo.indices) {println ("arrayListTwo [$] = >" + arrayListTwo [I])}

The output is as follows:

ArrayListTwo [0] = > 1 arrayListTwo [1] = > 3 arrayListTwo [2] = > 5 arrayListTwo [3] = > 7 arrayListTwo [4] = > 9

Traversing using the withIndex () method of the array

Example:

Var arrayListTwo = arrayOf (1 index,value 3 5 value 7 7) for ((index,value) in arrayListTwo.withIndex ()) {println ("index = > $index\ t value = > $value")}

The output is as follows:

Index = > 0 value = > 1 index = > 1 value = > 3 index = > 2 value = > 5 index = > 3 value = > 7 index = > 4 value = > 9

Traverse using the extension function of a list or array

An array or list has a member or extension function iterator () that implements the Iterator interface, and the interface provides two members, next () and hasNext (), or extension functions

It is generally used with while loops

You can look at the class Array.kt. You can see the iterator () function, which implements the Iterator interface.

/ * Creates an iterator for iterating over the elements of the array. * / public operator fun iterator (): Iterator

Look at the interface class Iterator.kt, which provides the hasNext () function and the next () function.

Public interface Iterator {/ * * Returns the next element in the iteration. * / public operator fun next (): t / * Returns `true` if the iteration has more elements. * / public operator fun hasNext (): Boolean}

Example:

Var arrayListThree = arrayOf var iterator: Iterator = arrayListThree.iterator () while (iterator.hasNext ()) {println (iterator.next ())}

The output is as follows:

2 a 3 false 9

9.kotlin stream really can.

Streaming brings great convenience to our collection operations. In fact, Java 8 also supports streaming. I just want to promote stream here.

The following examples are:

Val names = arrayOf ("Amy", "Alex", "Bob", "Cindy", "Jeff", "Jack", "Sunny", "Sara", "Steven") / / filter the names beginning with S val sName = names.filter {it.startsWith ("S")}. ToList () / / grouped and sorted by acronym val nameGroup = names.groupBy {it [0]} .toSortedMap (Comparator {key1) Key2-> key1.compareTo (key2)})

For more streaming, please search Java stream yourself

10. Write less and overload the method

Because kotlin supports default parameters, there are fewer method overloads when encapsulating methods.

If you do not have default parameters, you need to implement the following log printing, you need to write multiple methods:

Fun log (tag: String, content: String) {println ("tag:$tag-- > $content")} fun log (content: String) {log ("quanke", ")}

Only one method is required to use the default parameters:

Fun log (tag: String= "quanke", content: String) {println ("tag:$tag-- > $content")} Thank you for your reading. The above is the content of "Why do not use the grammatical thinking of Java to write Kotlin". After the study of this article, I believe you have a deeper understanding of why you should not use the grammatical thinking of Java to write Kotlin. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report