In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces "how to understand the inverter and covariant in Java". In the daily operation, I believe that many people have doubts about how to understand the inverter and covariant in Java. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the doubt of "how to understand the inverter and covariant in Java". Next, please follow the editor to study!
1. Inverter and covariant
Before introducing inverter and covariant, the principle of Liskov substitution (Liskov Substitution Principle, LSP) is introduced.
Liskov replacement principle
LSP was proposed by Barbara Liskov in 1987 and its definition is as follows:
All references to the base class (parent class) must be able to transparently use the objects of its subclasses.
LSP has the following four meanings:
The subclass fully has the methods of the parent class, and the concrete subclass must implement the abstract methods of the parent class.
You can add your own methods to the subclass.
When a subclass overrides or implements a method of the parent class, the formal parameters of the method are more relaxed than those of the parent method.
When a subclass overrides or implements a method of the parent class, the return value of the method is stricter than that of the parent class.
The first two meanings are easy to understand, and the latter two meanings will be explained in detail below. According to LSP, when we instantiate an object, we can instantiate it with its subclasses, such as:
Number num = new Integer (1)
Define
Inverters and covariates are used to describe inheritance relationships after type conversion (type transformation). They are defined: if An and B represent types, f (⋅) represents type conversions, and ≤ represents inheritance relationships (for example, A ≤ B indicates that An is a subclass derived from B.)
F (⋅) is contravariant, and f (B) ≤ f (A) holds when A ≤ B.
F (⋅) is covariant (covariant), and f (A) ≤ f (B) holds when A ≤ B.
F (⋅) is invariant, and the above two expressions are not true when A ≤ B, that is, there is no inheritance relationship between f (A) and f (B).
Type conversion
Next, let's take a look at the covariance, inverse, or invariance of common type conversions in Java.
Generics:
If f (A) = ArrayList, then is f (⋅) inverted, covariant or invariant? If it is an inverter, ArrayList is the parent type of ArrayList; if it is covariant, ArrayList is a subtype of ArrayList; if it is unchanged, there is no inheritance between the two. The object error instantiating list with ArrayList in the opening code indicates that the generics are immutable.
Array:
If f (A) = [] A, it is easy to prove that the array is covariant:
Number [] numbers = new Integer [3]
Call the method result = method (n); according to the principle of Liskov substitution, the type of the passed parameter n should be a subtype of the method parameter, that is, typeof (n) ≤ typeof (method's parameter), and result should be the base type of the return value of method, that is, typeof (methods's return) ≤ parameter (result):
Static Number method (Number num) {return 1;} Object result = method (new Integer (2)); / / correctNumber result = method (new Object ()); / / errorInteger result = method (new Integer (2)); / / error
In Java 1.4, when a subclass overrides (override) a parent class method, the type of the shape participating in the return value must be consistent with the parent class:
Class Super {Number method (Number n) {...}} class Sub extends Super {@ Override Number method (Number n) {...}}
Starting with Java 1.5, subclasses allow covariance to return more specific types when overriding parent class methods:
Class Super {Number method (Number n) {...}} class Sub extends Super {@ Override Integer method (Number n) {...}}
two。 Wildcards in generics
Realize the covariance and inversion of generics
Generics are immutable in Java, but sometimes you need to implement inverters and covariates. What should I do? At this point, wildcards? It came in handy:
Implemented the covariance of generics, such as:
List list = new ArrayList ()
Implemented the inversion of generics, such as:
List list = new ArrayList ()
Extends and super
Why do List list compile errors in add Integer and Float (in the opening code)? First, let's look at the implementation of add:
Public interface Listextends Collection {boolean add (E e);}
When the add method is called, the generic E automatically becomes, indicating that the type held by list is one of the subclasses derived from Number and Number, which contains the Integer type but does not specifically refer to the Integer type (Integer is like a backup! ), so a compilation error occurred during add Integer In order to call the add method, you can use the super keyword to implement:
List list = new ArrayList (); list.add (new Integer (1)); list.add (new Float (1.2f))
Indicates that the type held by list is one of the base classes of Number and Number, where Integer and Float must be subclasses of this type; so the add method can be called correctly. As you can see from the above example, extends determines the upper bound of generics, while super determines the lower bound of generics.
PECS
Now the question is: when to use extends and when to use super? "Effective Java" gives the answer:
PECS: producer-extends, consumer-super.
For example, a simple Stack API:
Public class Stack {public Stack (); public void push (E): public E pop (); public boolean isEmpty ();}
To implement the pushAll (Iterable src) method, stack the elements of the src one by one:
Public void pushAll (Iterablesrc) {for (E e: src) push (e)}
Suppose an object stack,src that instantiates Stack has Iterable and Iterable; will have a type mismatch error when calling the pushAll method, because generics in Java are immutable and neither Iterable nor Iterable are subtypes of Iterable. Therefore, it should be changed to
/ / Wildcard type for parameter that serves as an E producerpublic void pushAll (Iterable src) {for (E: src) push (e);}
To implement the popAll (Collection dst) method, take the elements in Stack and add them into dst in turn, if you don't use wildcards:
/ / popAll method without wildcard type-implementing public void popAll (Collectiondst) {while (! isEmpty ()) dst.add (pop ());}
Therefore, it should be changed to:
/ / Wildcard type for parameter that serves as an E consumerpublic void popAll (Collection dst) {while (! isEmpty () dst.add (pop ());}
In the above example, the E instance (produces E instances) is produced when the pushAll method is called, and the dst consumes the E instance (consumes E instances) when the popAll method is called. Naftalin and Wadler call PECS Get and Put Principle.
Java.util.Collections 's copy method (JDK1.7) perfectly interprets PECS:public staticvoid copy (List dest, List src) {int srcSize = src.size (); if (srcSize > dest.size ()) throw new IndexOutOfBoundsException ("Source does not fit in dest"); if (srcSize < COPY_THRESHOLD | | (src instanceof RandomAccess & dest instanceof RandomAccess)) {for (int item0; I)
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.