当前位置:网站首页>Generics, generic defects and application scenarios that 90% of people don't understand
Generics, generic defects and application scenarios that 90% of people don't understand
2022-07-05 09:52:00 【hi-dhl】
Author's brief introduction : hi Hello everyone , I am a dhl, Is maintaining its own Personal website , Focus on sharing the latest technology and original articles , involve Kotlin、Jetpack、 Algorithm animation 、 data structure 、 System source code wait .
Reprint note : Not authorized , Prohibited reproduced .
The full text is divided into Video version and Text version ,
- Text version : Text focuses on detail and depth , Some knowledge , The video is not easy to express , The text description is more accurate
- Video version : The video will be more intuitive , Read the text version , Watching video , The knowledge points will be clearer
Video version bilibili Address :https://b23.tv/AdLtUGf
Generics are no stranger to every developer , I often see it in the project , But there are many friends , Every time I see wildcards ? extends
、 ? super
、 out
、 in
I can't tell the difference between them , And under what circumstances .
Through this article, you will learn the following .
- Why generics
- Kotlin and Java The covariance of
- Kotlin and Java The inverse of
- wildcard
? extends
、? super
、out
、in
The differences and application scenarios - Kotlin and Java The difference of array covariance
- The defect of array covariance
- Application scenarios of covariance and inversion
Why generics
stay Java and Kotlin We often use sets in ( List
、 Set
、 Map
wait ) To store data , Various types of data may be stored in the collection , Now we have four data types Int
、 Float
、 Double
、 Number
, Let's say there's no generics , We need to create four collection classes to store the corresponding data .
class IntList{ ...... }
class FloatList{ ...... }
class DoubleList{ ...... }
class NumberList{ ...... }
......
more
If there are more types , You need to create more collection classes to store the corresponding data , This shows that it is impossible , Generics are a “ Universal type matcher ”, At the same time, it can make the compiler ensure type safety .
Generics will be concrete types ( Int
、 Float
、 Double
wait ) Use symbols instead of when declaring , When you use it , To specify a specific type .
// Use symbols instead of when declaring
class List<E>{
}
// stay Kotlin Use in , Specify the specific type
val data1: List<Int> = List()
val data2: List<Float> = List()
// stay Java Use in , Specify the specific type
List<Integer> data1 = new List();
List<Float> data2 = new List();
Generics help us solve the above problems , But new problems have arisen , We all know Int
、 Float
、 Double
yes Number
subtypes , Therefore, the following code can work normally .
// Kotlin
val number: Number = 1
// Java
Number number = 1;
Let's take three seconds to think , Whether the following code can be compiled normally .
List<Number> numbers = new ArrayList<Integer>();
The answer is no , As shown in the figure below , Compilation error .
This means that generics are immutable ,IDE Think ArrayList<Integer>
No List<Number>
subtypes , This assignment is not allowed , So how to solve this problem , This requires covariance , Covariance allows the above assignment to be legal .
Kotlin and Java The covariance of
- stay Java Wildcards are used in
? extends T
Represents covariance ,extends
The parent type is restrictedT
, among?
Indicates an unknown type , such as? extends Number
, As long as the type passed in when declaring isNumber
perhapsNumber
All subtypes of - stay Kotlin Key words in
out T
Represents covariance , Meaning and Java equally
Now let's modify the above code , Take three seconds to think , Whether the following code can be compiled normally .
// kotlin
val numbers: MutableList<out Number> = ArrayList<Int>()
// Java
List<? extends Number> numbers = new ArrayList<Integer>();
The answer is that you can compile normally , Covariant wildcards ? extends Number
perhaps out Number
Express acceptance Number
perhaps Number
The subtype is a collection of objects , Covariance relaxes constraints on data types , But relaxation comes at a price , We were thinking for three seconds , Whether the following code can be compiled normally .
// Koltin
val numbers: MutableList<out Number> = ArrayList<Int>()
numbers.add(1)
// Java
List<? extends Number> numbers = new ArrayList<Integer>();
numbers.add(1)
call add()
Method will fail to compile , Although covariance relaxes the constraints on data types , Acceptable Number
perhaps Number
The subtype is a collection of objects , But at the cost of Unable to add element , You can only get elements , So covariance can only be a producer , Provide data to the outside .
Why can't I add elements
because ?
Indicates an unknown type , So the compiler doesn't know what kind of data it will add to the collection , Therefore, it is simply not allowed to add elements to the collection .
But if you want the above code to compile and pass , Want to add elements to the collection , This requires inversion .
Kotlin and Java The inverse of
Inversion actually reverses the inheritance relationship , such as Integer
yes Number
Subtypes of , however Integer
Add the inverse wildcard ,Number
yes ? super Integer
Subclasses of , As shown in the figure below .
[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-8bRLR2Qd-1655947414076)(https://img.hi-dhl.com/16551339994410.jpg)]
- stay Java Wildcards are used in
? super T
Represent contravariant , among?
Indicates an unknown type ,super
Mainly used to restrict subtypes of unknown typesT
, such as? super Number
, As long as the declaration is passed inNumber
perhapsNumber
The parent type of the can - stay Kotlin Key words in
in T
Represent contravariant , Meaning and Java equally
Now let's simply modify the above code , Take three seconds to think about whether you can compile normally .
// Kotlin
val numbers: MutableList<in Number> = ArrayList<Number>()
numbers.add(100)
// Java
List<? super Number> numbers = new ArrayList<Number>();
numbers.add(100);
The answer can be compiled normally , Inverse wildcard ? super Number
Or keywords in
Reverse the inheritance relationship , Mainly used to restrict subtypes of unknown types , In the example above , The compiler knows that the subtype is Number
, So as long as it's Number
Subclasses of can be added .
Contravariant can add elements to the set , Can I get the elements ? Let's take three seconds to think about , Whether the following code can be compiled normally .
// Kotlin
val numbers: MutableList<in Number> = ArrayList<Number>()
numbers.add(100)
numbers.get(0)
// Java
List<? super Number> numbers = new ArrayList<Number>();
numbers.add(100);
numbers.get(0);
No matter call add()
Method or call get()
Method , Can be compiled normally , Now modify the above code , Think about whether you can compile normally .
// Kotlin
val numbers: MutableList<in Number> = ArrayList<Number>()
numbers.add(100)
val item: Int = numbers.get(0)
// Java
List<? super Number> numbers = new ArrayList<Number>();
numbers.add(100);
int item = numbers.get(0);
call get()
Method will fail to compile , because numbers.get(0)
The value obtained is Object
The type of , So it cannot be assigned directly to int
type , Contravariant is the same as covariant , Relaxed constraints on data types , But at the cost of Cannot read elements by generic type , That is, add... To the set int
Data of type , call get()
Method does not get int
Data of type .
For the content of this section , Let's briefly summarize .
keyword (Java/Kotlin) | add to | Read | |
---|---|---|---|
Covariance | ? extends / out | ||
Inversion | ? super / in |
Kotlin and Java The difference of array covariance
Whether it's Kotlin still Java The meaning of covariance and contravariant is the same , But the wildcards are different , But they also have differences .
Java Support array covariance , The code is as follows :
Number[] numbers = new Integer[10];
however Java Array covariance in is defective , Change the above code , As shown below .
Number[] numbers = new Integer[10];
numbers[0] = 1.0;
Can compile normally , But it will crash when running .
Because at first I will Number[]
Covariant transformation Integer[]
, Then I added... To the array Double
Data of type , So the operation will crash .
and Kotlin Our solution is very straightforward , Array covariance is not supported , There will be errors when compiling , For array inversion Koltin and Java Don't support .
Application scenarios of covariance and inversion
Covariant and inverse applications need to follow PECS(Producer-Extends, Consumer-Super) principle , namely ? extends
perhaps out
As a producer ,? super
perhaps in
As a consumer . The advantages of following this principle are , You can keep your code safe at compile time , Reduce the occurrence of unknown errors .
Covariant application
- stay Java Wildcards are used in
? extends
Represents covariance - stay Kotlin Key words in
out
Represents covariance
Covariant can only read data , Can't add data , So I can only be a producer , Provide data to the outside , So it can only be used to output , It is not used to input .
stay Koltin A covariant class in , Add before parameter out
After modification , This parameter is in the current class Can only be used as the return value of a function , Or modify the read-only attribute , The code is as follows .
// Normal compilation
interface ProduceExtends<out T> {
val num: T // For read-only properties
fun getItem(): T // Return value for function
}
// Compile failed
interface ProduceExtends<out T> {
var num : T // For variable attributes
fun addItem(t: T) // Parameters for function
}
When we determine that an object is only a producer , Provide data to the outside , Or as the return value of a method , We can use ? extends
perhaps out
.
- With Kotlin For example , for example
Iterator#next()
Method , Keyword usedout
, Returns each element in the collection
- With Java For example , for example
ArrayList#addAll()
Method , Wildcards are used? extends
Pass in the parameter Collection<? extends E> c
As a producer to ArrayList
Provide data .
Inverter applications
- stay Java Use wildcards in
? super
Represent contravariant - stay Kotlin Use keywords in
in
Represent contravariant
Inversion can only add data , Cannot read data by generics , So only as a consumer , Therefore, it can only be used to input , Cannot be used to output .
stay Koltin An inverse class in , Add before parameter in
After modification , This parameter is in the current class Can only be used as an argument to a function , Or modify variable attributes .
// Normal compilation , Parameters for function
interface ConsumerSupper<in T> {
fun addItem(t: T)
}
// Compile failed , Return value for function
interface ConsumerSupper<in T> {
fun getItem(): T
}
When we determine that an object is only a consumer , When passed in as a parameter , Only for adding data , We use wildcards ? super
Or keywords in
,
- With Kotlin For example , For example, extension methods
Iterable#filterTo()
, Keyword usedin
, Internally, it is only used to add data
- With Java For example , for example
ArrayList#forEach()
Method , Wildcards are used? super
I don't know if my friends have noticed , In the source code above , Different generic tags are used separately T
and E
, Actually, let's pay a little attention , There are several high-frequency generic tags in the source code T
、 E
、 K
、 V
wait , They are applied to different scenarios .
Marker | Application scenarios |
---|---|
T(Type) | class |
E(Element) | aggregate |
K(Key) | key |
V(Value) | value |
This is the end of the article , Thanks for reading , It's not easy to stick to originality , Welcome to 、 give the thumbs-up 、 Share it with your friends , I will continue to share original dry goods !!!
边栏推荐
- 基于模板配置的数据可视化平台
- Roll up, break 35 - year - old Anxiety, animation Demonstration CPU recording Function call Process
- Unity SKFramework框架(二十三)、MiniMap 小地图工具
- Evolution of Baidu intelligent applet patrol scheduling scheme
- What should we pay attention to when developing B2C websites?
- H.265编码原理入门
- MySQL installation configuration and creation of databases and tables
- Android 隐私沙盒开发者预览版 3: 隐私安全和个性化体验全都要
- Common fault analysis and Countermeasures of using MySQL in go language
- High performance spark_ Transformation performance
猜你喜欢
Principle and performance analysis of lepton lossless compression
Project practice | excel export function
LeetCode 556. Next bigger element III
Principle and performance analysis of lepton lossless compression
Common fault analysis and Countermeasures of using MySQL in go language
Unity SKFramework框架(二十二)、Runtime Console 运行时调试工具
一文读懂TDengine的窗口查询功能
How to empty uploaded attachments with components encapsulated by El upload
Unity skframework framework (XXII), runtime console runtime debugging tool
On July 2, I invite you to TD Hero online press conference
随机推荐
[sourcetree configure SSH and use]
微信小程序获取住户地区信息
Tdengine connector goes online Google Data Studio app store
盗版DALL·E成梗图之王?日产5万张图像,挤爆抱抱脸服务器,OpenAI勒令改名
How to empty uploaded attachments with components encapsulated by El upload
LeetCode 556. Next bigger element III
TDengine 已经支持工业英特尔 边缘洞见软件包
High performance spark_ Transformation performance
一文读懂TDengine的窗口查询功能
STM32 simple multi-level menu (array table lookup method)
如何正确的评测视频画质
LeetCode 31. Next spread
Mobile heterogeneous computing technology GPU OpenCL programming (Advanced)
Deep understanding of C language pointer
About getfragmentmanager () and getchildfragmentmanager ()
Online chain offline integrated chain store e-commerce solution
idea用debug调试出现com.intellij.rt.debugger.agent.CaptureAgent,导致无法进行调试
Uncover the practice of Baidu intelligent testing in the field of automatic test execution
[object array A and object array B take out different elements of ID and assign them to the new array]
Community group buying has triggered heated discussion. How does this model work?