Home Java javaTutorial Introduction to the knowledge of Java array covariance and generic invariance (with code)

Introduction to the knowledge of Java array covariance and generic invariance (with code)

Feb 23, 2019 pm 04:38 PM
java array

What this article brings to you is an introduction to the knowledge of Java array covariance and generic invariance (with code). It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you. help.

Variability is a big pitfall of OOP language invariance, and Java's array covariance is one of the old pitfalls. Because I stepped on it recently, I made a note. By the way, let’s also mention the degeneration of paradigms.

Before explaining array covariance, first clarify three related concepts, covariance, invariance and contravariance.

1. Covariance, invariance, contravariance

Suppose, I wrote such a piece of code for a restaurant

class Soup<T> {
    public void add(T t) {}
}
class Vegetable { }
class Carrot extends Vegetable { }
Copy after login

There is a generic class Soup, which represents soup made with ingredient T. Its method add(T t) represents adding ingredients to the soup. Add ingredient T. The Vegetable class represents vegetables, and the Carrot class represents carrots. Of course, Carrot is a subclass of Vegetable.

Then the question is, what is the relationship between Soup and Soup?

The first reaction is that Soup should be a subcategory of Soup, because carrot soup is obviously a vegetable soup. If that's the case, then take a look at the code below. Among them, Tomato means tomatoes, which is another subclass of Vegetable

Soup<Vegetable> soup = new Soup<Carrot>();
soup.add(new Tomato());
Copy after login

The first sentence is okay, Soup is a subclass of Soup, So you can assign the instance of Soup to the variable soup. The second sentence is no problem, because soup is declared as Soup type, and its add method receives a parameter of Vegetable type, and Tomato is Vegetable and has the correct type.

However, there is a problem when putting the two sentences together. The actual type of soup is Soup, and we passed an instance of Tomato to its add method! In other words, if we are making carrot soup with tomatoes, we will definitely not be able to make it. Therefore, although it is logically logical to regard Soup as a subclass of Soup, it is flawed during use.

So, what is the relationship between Soup and Soup? Different languages ​​have different understandings and implementations. To sum up, there are three situations.

(1) If Soup is a subclass of Soup, the generic Soup is said to be covariant
(2) If Soup and Soup ; are two unrelated classes, then the generic Soup is said to be invariant
(3) If Soup is the parent class of Soup, then the generic Soup is said to be the inverse changing. (However, contravariance is not common)

After understanding the concepts of covariance, invariance and contravariance, let’s look at the implementation of Java. Java's general generics are immutable, which means Soup and Soup are two unrelated classes, and instances of one class cannot be assigned to variables of the other class. Therefore, the above code that uses tomatoes to make carrot soup actually cannot be compiled at all.

2. Array covariance

In Java, arrays are basic types, not generics, and there is no such thing as Array . But it's very similar to a generic, in that it's a type built from another type. Therefore, arrays must also be considered mutable.

Different from the immutability of generics, Java arrays are covariant. In other words, Carrot[] is a subclass of Vegetable[]. The examples in the previous section have shown that covariance can sometimes cause problems. For example, the following code

Vegetable[] vegetables = new Carrot[10];
vegetables[0] = new Tomato(); // 运行期错误
Copy after login

Because arrays are covariant, the compiler allows Carrot[10] to be assigned to variables of type Vegetable[], so this The code can be compiled successfully. It's only during runtime, when the JVM actually tries to insert a tomato into a pile of carrots, that something big goes wrong. Therefore, the above code will throw an exception of type java.lang.ArrayStoreException during runtime.

Array covariance is one of Java’s famous historical baggage. Be careful when using arrays!

If you replace the array in the example with a List, the situation will be different. Like this

ArrayList<Vegetable> vegetables = new ArrayList<Carrot>(); // 编译期错误
vegetables.add(new Tomato());
Copy after login

ArrayList is a generic class and it is immutable. Therefore, there is no inheritance relationship between ArrayList and ArrayList, and this code will report an error during compilation.

Although both pieces of code will report errors, compile-time errors are usually easier to handle than run-time errors.

3. When generics also want covariance and contravariance

Generics are immutable, but in some scenarios we Still hope it can covariate. For example, there is a young lady who drinks vegetable soup every day to lose weight

class Girl {
    public void drink(Soup<Vegetable> soup) {}
}
Copy after login

我们希望drink方法可以接受各种不同的蔬菜汤,包括Soup和Soup。但受到不变性的限制,它们无法作为drink的参数。

要实现这一点,应该采用一种类似于协变性的写法

public void drink(Soup<? extends Vegetable> soup) {}
Copy after login

意思是,参数soup的类型是泛型类Soup,而T是Vegetable的子类(也包括Vegetable自己)。这时,小姐姐终于可以愉快地喝上胡萝卜汤和西红柿汤了。

但是,这种方法有一个限制。编译器只知道泛型参数是Vegetable的子类,却不知道它具体是什么。所以,所有非null的泛型类型参数均被视为不安全的。说起来很拗口,其实很简单。直接上代码

public void drink(Soup<? extends Vegetable> soup) {
    soup.add(new Tomato()); // 错误
    soup.add(null); // 正确}
Copy after login

方法内的第一句会在编译期报错。因为编译器只知道add方法的参数是Vegetable的子类,却不知道它具体是Carrot、Tomato、或者其他的什么类型。这时,传递一个具体类型的实例一律被视为不安全的。即使soup真的是Soup类型也不行,因为soup的具体类型信息是在运行期才能知道的,编译期并不知道。

但是方法内的第二句是正确的。因为参数是null,它可以是任何合法的类型。编译器认为它是安全的。

同样,也有一种类似于逆变的方法

public void drink(Soup<? super Vegetable> soup) {}
Copy after login

这时,Soup中的T必须是Vegetable的父类。

这种情况就不存在上面的限制了,下面的代码毫无问题

public void drink(Soup<? super Vegetable> soup) {
    soup.add(new Tomato());
}
Copy after login

Tomato是Vegetable的子类,自然也是Vegetable父类的子类。所以,编译期就可以确定类型是安全的。

The above is the detailed content of Introduction to the knowledge of Java array covariance and generic invariance (with code). For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Roblox: Bubble Gum Simulator Infinity - How To Get And Use Royal Keys
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Fusion System, Explained
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers Of The Witch Tree - How To Unlock The Grappling Hook
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1666
14
PHP Tutorial
1273
29
C# Tutorial
1253
24
Revealing Five Efficient Java Array Deduplication Methods Revealing Five Efficient Java Array Deduplication Methods Dec 23, 2023 pm 02:46 PM

Five efficient Java array deduplication methods revealed In the Java development process, we often encounter situations where we need to deduplicate arrays. Deduplication is to remove duplicate elements in an array and keep only one. This article will introduce five efficient Java array deduplication methods and provide specific code examples. Method 1: Use HashSet to deduplicate HashSet is an unordered, non-duplicate collection that automatically deduplicates when adding elements. Therefore, we can use the characteristics of HashSet to deduplicate arrays. public

Common ways to add elements to Java arrays Common ways to add elements to Java arrays Feb 21, 2024 am 11:21 AM

Common ways to add elements to Java arrays, specific code examples are required In Java, an array is a common data structure that can store multiple elements of the same type. In actual development, we often need to add new elements to the array. This article will introduce common methods of adding elements to arrays in Java and provide specific code examples. A simple way to create a new array using a loop is to create a new array, copy the elements of the old array into the new array, and add the new elements. The code example is as follows: //original array i

What are the common methods of java arrays? What are the common methods of java arrays? Jan 02, 2024 pm 04:49 PM

Commonly used methods include length attribute, copy array, array traversal, array sorting, array conversion to string, etc. Detailed introduction: 1. Length attribute: used to get the length of an array. It is an attribute rather than a method. Example: int[] arr = {1, 2, 3}; int length = arr.length;; 2. Copy the array: Use the System.arraycopy() method or the copyOf() method of the Arrays class to copy the contents of the array to a new Arrays etc.

Detailed explanation of five classic Java array deduplication algorithms Detailed explanation of five classic Java array deduplication algorithms Dec 23, 2023 am 10:01 AM

Detailed explanation of five classic Java array deduplication algorithms In Java programming, you often encounter situations where you need to perform deduplication operations on arrays, that is, remove duplicate elements in the array and retain unique elements. The following will introduce five classic Java array deduplication algorithms and provide corresponding code examples. Using HashSet HashSet is a collection class in Java that automatically removes duplicate elements. This feature can be used to quickly achieve array deduplication. Code example: importjava.util.Arr

Solution to ArrayIndexOutOfBoundsException exception in Java Solution to ArrayIndexOutOfBoundsException exception in Java Jun 25, 2023 am 11:02 AM

Java is a widely used programming language that provides programmers with many practical and powerful tools and features. When writing Java programs, you may encounter various exceptions. Among them, ArrayIndexOutOfBoundsException is a common exception. This exception is triggered when we try to access an element that does not exist in the array. In this article, we will discuss ArrayIndexOutOfBoundsExc in Java in detail

How to use arrays and collections for data storage and manipulation in Java How to use arrays and collections for data storage and manipulation in Java Oct 18, 2023 am 08:15 AM

How to use arrays and collections for data storage and operation in Java In Java programming, arrays and collections are commonly used methods of data storage and operation. An array is a container used to store data of the same type, while a collection is an object composed of multiple elements. The basic method of using arrays for data storage and manipulation is as follows: Declaring an array variable To use an array, you first need to declare an array variable. An array variable can be declared using the following syntax: dataType[]arrayName; where dataT

An in-depth analysis of five practical methods for deduplicating Java arrays An in-depth analysis of five practical methods for deduplicating Java arrays Dec 23, 2023 am 09:21 AM

An in-depth analysis of five practical methods for deduplicating Java arrays. In Java, processing arrays is a very common operation. Array deduplication is a problem often encountered in actual development. This article will provide an in-depth analysis of five practical methods for Java array deduplication and provide specific code examples. 1. Use HashSet to remove duplicates. HashSet is a collection in Java that has the function of automatic deduplication. We can use the characteristics of HashSet to add elements in the array to HashSet to achieve the effect of deduplication.

Tips and things to note when adding elements to an array in Java Tips and things to note when adding elements to an array in Java Jan 03, 2024 pm 02:01 PM

Tips and precautions for adding elements to arrays in Java In Java, arrays are a very common and important data structure. It can store a set of elements of the same type, and these elements can be accessed and modified through indexes. In practical applications, we often need to dynamically add elements to an array. This article will introduce some tips and precautions for adding elements to arrays in Java, and provide corresponding code examples. Use dynamic array (ArrayList) to add elements Dynamic array ArrayList is

See all articles