Вступление
Подстановочный знак ( ?
) может помочь нам написать программу более понятным способом.
Он используется для представления неизвестного типа и никогда не используется в качестве аргумента типа для вызова универсального метода, создания экземпляра универсального класса или супертипа.
Пример
Давайте предположим, что у нас есть иерархия объектов:
- Класс
Animal
наследуется отОбъект
тривиально - Классы
Собака
иКошка
наследуются отЖивотного
- Класс
Золотистый ретривер
наследуется отСобаки
В общем, есть 3 способа использовать подстановочный знак:
Верхняя граница:
пустое удовольствие(Список расширяет список животных>)
Этот список входных данных параметризован по не более типаЖивотное
(может быть любым подтипомЖивотного
)Нижняя граница:
пустое удовольствие(Список супер Животное> список)
Этот список входных данных параметризован по по крайней мере типЖивотное
(может быть любым супертипомЖивотного
)Неограниченный:
пустое веселье(список список) {список.очистить();}
- Здесь нам все равно, какой тип списка, так как
clear()
не зависит от типа. - Если бы мы должны были использовать только методы, определенные в
Объект
, то неограниченный подстановочный знак работает нормально.
- Здесь нам все равно, какой тип списка, так как
Демонстрационный код Java
Смотрите следующий код, WildcardDemo.java
, для лучшего понимания.
Сначала попробуйте скомпилировать его с помощью javac WildcardDemo.java
и увидеть консоль ошибок:)
Во-вторых, чтобы успешно скомпилировать код, обратите внимание, что есть 2 строки, помеченные как //X (не удается скомпилировать)
, вы должны прокомментировать их, чтобы скомпилировать код.
Код полностью прокомментирован. Не стесняйтесь оставлять любые комментарии, если вы не понимаете.
import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Our Object Hierarchy: * * Object * | * Animal * / \ * Dog Cat * | * GoldenRetriever */ public class WildcardDemo { private class Animal {} private class Dog extends Animal {} private class Cat extends Animal {} private class GoldenRetriever extends Dog {} // `animals` is parameterized over "at most" type `Animal` private void funExtends(List extends Animal> animals) { // Can't add a Dog (subtype) to the `animals` because it may // contain something "lower than an Animal". // For example, it might be `List` or `List ` animals.add(new Dog()); // X (can't compiled) // Can't put anything into a type declared with an extends // wildcard except for the value `null`, which is a subtype // of every reference type animals.add(null); // Can retrieve an `Animal`, because any subtype of `Animal` // must be an `Animal` Animal animal = animals.get(0); System.out.println(animal.getClass().toString()); } // `animals` is parameterized over "at least" type `Animal` private void funSuper(List super Animal> animals) { // Can add a `Dog` (subtype) to the `animals` because a `Dog` // is guaranteed an `Animal` or any supertype of an `Animal` animals.add(new Dog()); // Can't get anything out from a type declared with a super // wildcard except for a value of type `Object`, which is a // super type of every reference type Animal animal = animals.get(0); // X (can't compiled) Object object = animals.get(1); System.out.println(object.getClass().toString()); } private List getAnimals() { return new ArrayList<>(Arrays.asList( new GoldenRetriever(), new Cat() ) ); } public static void main(String[] args) { WildcardDemo demo = new WildcardDemo(); List animals = demo.getAnimals(); demo.funExtends(animals); demo.funSuper(animals); } }
Оригинал: “https://dev.to/walkccc/java-wildcards-demo-554f”