当前位置:网站首页>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 !!!
边栏推荐
- cent7安装Oracle数据库报错
- Dry goods sorting! How about the development trend of ERP in the manufacturing industry? It's enough to read this article
- 剪掉ImageNet 20%数据量,模型性能不下降!Meta斯坦福等提出新方法,用知识蒸馏给数据集瘦身...
- 【饿了么动态表格】
- 【C语言】动态内存开辟的使用『malloc』
- LeetCode 31. Next spread
- On July 2, I invite you to TD Hero online press conference
- Roll up, break 35 - year - old Anxiety, animation Demonstration CPU recording Function call Process
- MySQL installation configuration and creation of databases and tables
- Principle and performance analysis of lepton lossless compression
猜你喜欢
卷起来,突破35岁焦虑,动画演示CPU记录函数调用过程
H. 265 introduction to coding principles
Roll up, break through 35 year old anxiety, and animate the CPU to record the function call process
基于模板配置的数据可视化平台
Why don't you recommend using products like mongodb to replace time series databases?
Vs code problem: the length of long lines can be configured through "editor.maxtokenizationlinelength"
The most comprehensive promotion strategy: online and offline promotion methods of E-commerce mall
Android privacy sandbox developer preview 3: privacy, security and personalized experience
使用el-upload封装得组件怎么清空已上传附件
百度评论中台的设计与探索
随机推荐
Observation cloud and tdengine have reached in-depth cooperation to optimize the cloud experience of enterprises
单片机原理与接口技术(ESP8266/ESP32)机器人类草稿
Unity SKFramework框架(二十二)、Runtime Console 运行时调试工具
MySQL installation configuration and creation of databases and tables
盗版DALL·E成梗图之王?日产5万张图像,挤爆抱抱脸服务器,OpenAI勒令改名
【技术直播】如何用 VSCode 从 0 到 1 改写 TDengine 代码
The comparison of every() and some() in JS uses a power storage plan
Solve liquibase – waiting for changelog lock Cause database deadlock
Oracle combines multiple rows of data into one row of data
Resolve the horizontal (vertical) sliding conflict between viewpager and WebView
揭秘百度智能测试在测试自动执行领域实践
SMT32H7系列DMA和DMAMUX的一点理解
【对象数组的排序】
oracle 多行数据合并成一行数据
[object array A and object array B take out different elements of ID and assign them to the new array]
[app packaging error] to proceed, either fix the issues identified by lint, or modify your build script as follow
写入速度提升数十倍,TDengine 在拓斯达智能工厂解决方案上的应用
【两个对象合并成一个对象】
How to empty uploaded attachments with components encapsulated by El upload
tongweb设置gzip