Hi everyone, I am DHL. ByteCode, focus on the latest technology to share original articles, involving Kotlin, Jetpack, algorithm animation, data structure, system source code, LeetCode/point Offer/multithreading/domestic and foreign large factory algorithm problems and so on.
Kotlin 1.5 announced a blockbuster feature, Value Class, which is a very useful feature that improves code readability while also improving performance as the compiler optimizes it further and reduces object creation.
Inner class, data Class, sealed Class, sealed Interface, inline class, value class, etc. Sealed Class and Sealed Interface have written several articles on sealed Class and sealed Interface.
- What is Kotlin Sealed? Why does Google use it all
- The sealed class in Kotlin is superior to the tagged class
- The Kotlin hermetic class evolved
Today’s article focuses on inline classes and value classes.
In this article you will learn the following:
- What is an inline function?
- When are inline functions used?
- What is the
inline class
? - What is the
value class
?value class
Cannot be inheritedvalue class
You can implement interfaces- Inlining is lost when the passed object is empty
value class
It is prohibited to use= = =
You can use= =
inline class
和value class
What’s the difference?- How does Java call a function that accepts an inline class?
Inline function
In Kotlin, inline-functions are used to inline functions. To improve performance and reduce object creation, a call to a function with an inline modifier puts the code inside the method in place of the call. The inline function code is shown below.
Fun testInline() {printByteCode()} Inline fun printByteCode() {println("printByteCode")} public static final after compiling void testInline() { String var1 = "printByteCode"; System.out.println(var1); }Copy the code
Inline – decorated functions apply to the following cases
inline
Modifiers are good for taking a function as an argument to another function, such as a higher-order functionfilter
、map
、joinToString
Or some individual functionrepeat
inline
The operators apply to andreified
Operators are used together- If the function body is short, use
inline
Operators improve efficiency
Android Studio gives a big warning if you use inline modifiers to mark normal functions, as shown in the figure below. This is to prevent the performance penalty of inline operator abuse.
But if the function body is very short and you want to improve efficiency with the inline operator and eliminate warnings, you can check out the few Kotlin tips and parse the use of Kotlin annotations in your project in article 3.
Example repository address: https://github.com/hi-dhl/KtKit
Inline class
Inline classes are an overlooked and very useful feature. Sometimes the necessary business logic involves encapsulating basic data types, strings, and so on in a Model, and then encapsulating methods in the Model to check, validate, and so on.
After the parameters are wrapped, the wrapper object needs to be created, and the creation of the object is allocated in the heap. When the data volume is very large, the performance cost is very high, for example: memory footprint, run-time efficiency, frequent object creation, resulting in the GC collecting a large number of objects, and so on.
Primitive data types, strings, and so on are optimized by the JVM at runtime, but if you wrap these parameters in a class, the wrapper class does nothing and still creates objects in the heap.
So to reduce the performance penalty and avoid object creation, Kotlin introduced an inline class inline-classes. The inline class can pass only one parameter in the constructor, which is declared with val and replaced by the value passed in when compiled, as shown below.
inline class User(val name: String) fun testInline() {println(User("DHL"))} public static final void testInline() { System.out.println("DHL"); }Copy the code
As you can see, the compiled Java code does not create additional objects, and the objects created in Kotlin are replaced with the values passed in.
How does Java call a function that accepts an inline class
When a function is declared in Kotlin and inline class is passed as an argument, the name of the function is scrambled when compiled into Java code, as shown below.
inline class User(val name: String) fun login(user: Public static final void login_FY_U7ig/* $FF was: login-fy_u7ig */(@notnull String User) {} public static final void login_FY_U7ig/* $FF was: login-fy_U7ig */(@notnull String User) {}Copy the code
The compiled function name is scrambled, for example login-FY_u7ig. There is a problem, however, that Java cannot call a function that accepts an inline class, as shown below.
inline class User(val name: String) fun login(user: User) { } fun login(passwd: String) {} // Kotlin compiling normal login(User("DHL")) login("ByteCode") // Java compiling failed mainkt.login ("DHL");Copy the code
Called from Kotlin, it compiles normally, but the Java call fails due to inlining, as shown below.
To make it work in Java, the @jVMName annotation was added to change the function name to solve the problem, as shown below.
inline class User(val name: String) @JvmName("loginWithName") fun login(user: User) { } fun login(passwd: String) {} // Kotlin compile properly login(User("DHL")) login("ByteCode") // Java compile properly mainkt.loginWithName ("DHL");Copy the code
So Inline classes and Value classes without the @jVMName annotation will have this problem. The name of the generated function is scrambled to prevent method overload conflicts or unexpected Java calls.
Inline classes were introduced in Kotlin 1.3 and went into a stable version in Kotlin 1.5, discarding Inline modifiers and introducing Value classes.
What are Value classes
Inline classes are a subset of Value classes. Value classes are more optimized than Inline classes. Only one parameter can be passed in the constructor, which needs to be declared with val. In the future, multiple parameters can be added to the constructor, but each parameter needs to be declared with val, as shown below.
It will be more widely used in the future if multiple parameters are supported.
After upgrading to Kotlin 1.5, Inline classes will be deprecated, as shown below, and the compiler will warn you.
The only change is to inline the syntax with value and then add the @jvminline annotation.
@JvmInline
value class User(val name: String)
Copy the code
The compiled effect is the same as Inline classes, so future cases will use Value classes.
Value classes cannot be inherited
Because a value class is compiled with fianl modifiers, it cannot be inherited, nor can it inherit from other classes, as shown in the figure below.
Value classes can implement interfaces
Although a Value class cannot inherit from another class, it can implement an interface, as shown below.
interface LoginInterface @JvmInline value class User(val name: String) : LoginInterface fun testInline() {println(User("DHL"))} public static final void testInline() {User var0 = User.box-impl(User.constructor-impl("DHL")); System.out.println(var0); } public static final User box_impl/* $FF was: box-impl*/(String v) { return new User(v); }Copy the code
As the code shows, when the Value class implements the interface and loses the inlining effect, the User object is still created in the heap. There is no inlining effect except when the interface is implemented, and the inlining effect is also lost when the object is empty.
Inlining is lost when the passed object is empty
When the constructor takes a primitive data type and passes a value class object with an empty value, the inline effect is lost, as shown below.
@JvmInline value class User(val age: Int) fun login(user: User?) : Int = user? .age ? : 0 fun testInline() {println(login(User(10))} public static final int login_js0Jwf8/* $FF was: login-js0Jwf8*/(@Nullable User user) { return user ! = null ? user.unbox-impl() : 0; } public static final void testInline() { int var0 = login-js0Jwf8(User.box-impl(10)); System.out.println(var0); } public static final User box_impl/* $FF was: box-impl*/(int v) { return new User(v); }Copy the code
As you can see, the User object is still created in the heap, losing the inline effect, because Int cannot be directly converted to NULL.
When the constructor takes a String and the value class object passed is empty, the inline effect is not affected, as shown below.
@JvmInline value class User(val name: String) fun login(user: User?) : String = user? .name ?: "" fun testInline() {println(login(User("DHL")))} public static final String login_js0Jwf8/* $FF was: login-js0Jwf8*/(@Nullable String user) { // ...... return var10000; } public static final void testInline() { String var0 = login-js0Jwf8("DHL"); System.out.println(var0); }Copy the code
The compiled Java code does not create an object, and the User parameter passed to the method login is replaced with the String value passed in.
Value class Disables the use of === you can use ==
For more information on the differences between the == and == operators in Kotlin, and in which scenarios they are used, see the == and == in Kotlin debunked here.
Kotlin provides two ways to compare objects.
-
Compare the structures of objects to be equal (== or equals)
The == operator in Kotlin is equivalent to equals, which is used to compare the structure of objects to be equal. In many cases, equals is used because, for floating-point types Float and Double, its implementation does not follow the IEEE 754 floating-point standard.
-
Compare whether references to objects are equal (===)
The operator === in Kotlin is used to compare whether references to objects refer to the same object, which is equivalent to == at runtime for primitive data type ===.
The value class is a special operator that disallows the use of operator ===, as shown in the figure below, and the compiler will issue a warning.
Because the operator === is used to compare references to objects for equality, it is eventually replaced by the value passed in because of inlining.
But the operator ==, which is used to compare the structures of objects for equality, is unaffected, as shown below.
Fun testInline() {val u1 = User("DHL") val u2 = User("DHL") println(u1 == u2)} public static final void fun testInline() {val u1 = User("DHL") val u2 = User("DHL") testInline() { String u1 = "DHL"; String u2 = "DHL"; boolean var2 = User.equals-impl0(u1, u2); System.out.println(var2); }Copy the code
A “like” would be the biggest encouragement if it helps
More code, more articles
Welcome to the public account: ByteCode, continue to share the latest technology
Finally, recommend long-term update and maintenance projects:
-
Personal blog, will all articles classification, welcome to check hi-dhl.com
-
KtKit compact and practical, written in Kotlin language tool library, welcome to check KtKit
-
Androidx-jetpack-practice androidX-Jetpack-practice androidX-Jetpack-practice androidX-Jetpack-Practice androidX-Jetpack-Practice
-
LeetCode/multiple thread solution, language Java and Kotlin, including a variety of solutions, problem solving ideas, time complexity, spatial complexity analysis
- Job interview with major companies at home and abroad
- LeetCode: Read online
Must-read articles these days
- Google has announced the abandonment of the LiveData.observe method
- One detail to note when using Kotlin
- Follow the source data structure | circular queue
- Diagram ArrayDeque is faster than LinkedList
- Why not recommend ArrayDeque instead of Stack
- | algorithm animation diagrams are “abandoned” Java stack, why still use
- Kotlin code affecting Performance (1)
- Jetpack Splashscreen parsing | power generation IT migrant workers get twice the result with half the effort
- Kotlin’s Technique and Analysis (3)
- Kotlin’s Technique and Principle Analysis that few people know (II)
- Kotlin’s Technique and Principle Analysis that few people know (1)
- Uncover the == and === in Kotlin
- The Kotlin hermetic class evolved
- The sealed class in Kotlin is superior to the tagged class
- What is Kotlin Sealed? Why does Google use it all
- Android 12 behavior changes that affect applications
- AndroidStudio
- Kotlin StateFlow search features practice DB + NetWork
- The end of the Kotlin plugin and the rise of ViewBinding