当前位置:网站首页>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 !!!
边栏推荐
- 【饿了么动态表格】
- How to use sqlcipher tool to decrypt encrypted database under Windows system
- SQL learning alter add new field
- [app packaging error] to proceed, either fix the issues identified by lint, or modify your build script as follow
- MYSQL 对字符串类型排序不生效问题
- 盗版DALL·E成梗图之王?日产5万张图像,挤爆抱抱脸服务器,OpenAI勒令改名
- 解决idea调试过程中liquibase – Waiting for changelog lock….导致数据库死锁问题
- [technical live broadcast] how to rewrite tdengine code from 0 to 1 with vscode
- 美图炒币半年亏了3个亿,华为被曝在俄罗斯扩招,AlphaGo的同类又刷爆一种棋,今日更多大新闻在此...
- 一文读懂TDengine的窗口查询功能
猜你喜欢
First understanding of structure
A keepalived high availability accident made me learn it again
正式上架!TDengine 插件入驻 Grafana 官网
The popularity of B2B2C continues to rise. What are the benefits of enterprises doing multi-user mall system?
干货整理!ERP在制造业的发展趋势如何,看这一篇就够了
Data visualization platform based on template configuration
Node-RED系列(二九):使用slider与chart节点来实现双折线时间序列图
Android privacy sandbox developer preview 3: privacy, security and personalized experience
How Windows bat script automatically executes sqlcipher command
La voie de l'évolution du système intelligent d'inspection et d'ordonnancement des petites procédures de Baidu
随机推荐
Tdengine offline upgrade process
Tutorial on building a framework for middle office business system
微信小程序获取住户地区信息
一文读懂TDengine的窗口查询功能
Roll up, break through 35 year old anxiety, and animate the CPU to record the function call process
uni-app---uni.navigateTo跳转传参使用
[sorting of object array]
[technical live broadcast] how to rewrite tdengine code from 0 to 1 with vscode
Observation cloud and tdengine have reached in-depth cooperation to optimize the cloud experience of enterprises
Data visualization platform based on template configuration
Android SQLite database encryption
Tdengine connector goes online Google Data Studio app store
Principle and performance analysis of lepton lossless compression
oracle 多行数据合并成一行数据
Node-RED系列(二九):使用slider与chart节点来实现双折线时间序列图
Unity skframework framework (24), avatar controller third person control
Fluent development: setting method of left and right alignment of child controls in row
Apache DolphinScheduler 系统架构设计
TDengine 离线升级流程
Tdengine can read and write through dataX, a data synchronization tool