Trust attribute and interval of kotlin Development Notes

preface

This article mainly introduces the relevant contents of kotlin delegate attributes and intervals for your reference and learning. Let's take a look at the detailed introduction.

Delegate properties

There are some common attribute types. Although we can implement them manually every time we need them, it would be better if we could implement them only once and put them into a library. Examples include

To cover these (and other) situations, kotlin supports delegate attributes:

Delegate property is a property that has getters and optional setters through delegate implementation, and allows reusable custom properties to be implemented. For example:

The delegate object must implement an operator with a getValue () method and a setValue () method to implement read / write properties. These methods will accept the metadata containing the object instance and the attribute as additional parameters. When a class declares delegate properties, the code generated by the compiler will be similar to the following java code.

Some static attribute metadata is added to the class. The delegate is initialized in the class constructor and called every time the attribute is read and written.

Delegate instance

In the above example, a new delegate instance is created to implement the properties. This requires that the implementation of the delegation be stateful. For example, when the calculation results are cached internally:

At the same time, when additional parameters are required, a new delegate instance needs to be created and passed to the constructor.

However, in some cases, only one delegate instance is required to implement any attribute: when the delegate is stateless and the only variable it needs is the provided object instance and delegate name, it can be declared as object instead of class to implement a single instance delegate.

For example, the following singleton delegate retrieves the fragment matching the given tag from the Android activity.

Similarly, any existing class can be extended to become a delegate. GetValue () and setValue () can also be declared as extension methods. Kotlin has provided built-in extension methods to allow map and mutablemap instances to be used as delegates with attribute names as keys.

If you choose to reuse the same local delegate instance to implement multiple attributes in a class, you need to initialize the instance in the constructor.

Note: starting with kotlin 1.1, method local variables can also be declared as delegate properties. In this case, the delegate can not initialize until the variable is declared inside the method, instead of performing initialization in the constructor.

generic delegate

Delegate methods can also be declared generic, so that different types of attributes can reuse the same delegate class.

However, if a generic delegate is used for the basic type as in the above example, even if the declared basic type is not empty, the boxing and unpacking operations will be triggered every time the attribute is read and written.

Note: for delegate properties of non empty basic types, it is better to use a specific delegate class of a given type instead of a generic delegate to avoid the additional cost of boxing each time you access the property.

Standard entrustment: lazy ()

For common situations, kotlin provides some standard delegates, such as delegates. Notnull(), delegates. Observable(), and lazy().

Lazy () is a delegate that calculates the initial value of the property through the given lambda value at the first reading and returns the read-only property.

This is a simple way to delay high consumption initialization to its real need, while maintaining code readability and improving performance.

It should be noted that lazy () is not an inline function, and the passed lambda parameter will also be compiled into an additional function class and will not be inline into the returned delegate object.

It is often overlooked that lazy () has an optional mode parameter to determine which of the three delegates should be returned:

The default mode lazythreadsafetymode.synchronized will provide a relatively expensive double check lock to ensure that the initialization block can be executed safely once the attribute can be read from multiple threads.

If you are sure that the property will only be accessed in a single thread (such as the main thread), you can choose lazythreadsafetymode.none instead, so as to avoid the additional cost of using locks.

section

Interval is a special expression used to represent a finite set of values in kotlin. The value can be of any comparable type. These expressions are in the form of creating methods that declare the closedrange interface. The main method to create an interval is the... Operator method.

contain

The main function of interval expression is to use in and! The in operator implements include and exclude.

The implementation optimizes the intervals of non empty basic types (including the values of int, long, byte, short, float, double and char), so the above code can be optimized as follows:

Zero extra expense and no extra object overhead. Intervals can also be included in the when expression:

Compared with a series of if {...} else if {...} code blocks, this code improves the readability of the code without reducing efficiency. However, if there is at least one indirect call between declaration and use, range will have some small additional overhead.

For example, the following code:

An additional intrange object will be created after compilation:

The method of declaring the getter of the attribute as inline cannot avoid the creation of this object. This is a point that the kotlin 1.1 compiler can optimize. At least these specific interval classes avoid boxing operations.

Note: try to declare the interval of non empty basic type directly during use, and do not call it indirectly to avoid the creation of additional interval classes. Or directly declare it as a constant to reuse.

Intervals can also be used for other non basic types that implement comparable.

In this case, the final implementation will not be optimized, and a closedrange object will always be created, as shown in the following compiled code:

Iteration: for loop

Integer intervals (other basic types besides float and double) are also series: they can be iterated. This replaces the classic java for loop with a shorter expression.

Compiler optimized code achieves zero overhead:

If you want to reverse the iteration, you can use the downto() infix method instead of..:

After compilation, this also achieves zero overhead:

However, other iterator parameters are not so well optimized. The reverse iteration also has the same result, using the reversed () method in combination with the interval:

The compiled code is not as small as it seems:

A temporary intrange object is created to represent the interval, and then another intprogress object is created to reverse the value of the former.

In fact, any combination of more than one method to create a progression will generate similar code to create at least two tiny progressive objects.

This rule also applies to using the step () infix method to operate progressive steps, even if there is only one step:

As a secondary hint, when the generated code reads the last attribute of intprogress, it will determine the accurate final value through small calculation of boundary and step size. In the code above, the final value is 9.

Finally, the until () infix function is also useful for iterations, which (the execution result) does not contain a maximum value.

Unfortunately, the compiler does not optimize for this classic inclusion interval, and the iterator will still create interval objects:

This is another point that kotlin 1.1 can improve. At the same time, you can optimize the code by writing:

explain:

For the internal iteration of the for loop, it is best to use only a separate method of the interval expression to call.. or downto () to avoid the creation of additional temporary progressive objects.

Iteration: foreach ()

As an alternative to the for loop, it may be more attractive to use the interval inline extension method foreach () to achieve similar effects.

But if you look closely at the foreach () method signature used here, you will notice that there is no optimization interval, but only Iterable, so you need to create an iterator. The following is the Java form of the compiled code:

This code is more inefficient than the former because an additional intiterator needs to be created in order to create an intrange object. But at least it generates values of basic types. When iterating over an interval, it is best to use only the for loop instead of the foreach () method on the interval to avoid creating an additional iterator.

Iterations: Collections

The kotlin standard library provides built-in indexes extension properties to generate arrays and collection intervals.

Surprisingly, the iteration of this indices has been optimized by the compiler:

From the above code, we can see that the intrange object is not created, and the iteration of the list runs in the most efficient way.

This applies to arrays and classes that implement collection, so if you expect the same iterator performance, you can try to use your own indexes extension property on a specific class.

However, after compiling, we can find that this is not so efficient, because the compiler cannot intelligently avoid the generation of interval objects:

Therefore, I would recommend that you avoid declaring custom lastindex extension attributes:

Note: when the iteration does not declare a user-defined collection of collection, write your own sequence interval directly in the for loop instead of relying on methods or attributes to generate intervals, so as to avoid the creation of interval objects.

summary

The above is the whole content of this article. I hope the content of this article has a certain reference value for your study or work. If you have any questions, you can leave a message. Thank you for your support for programming tips.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>