2008-09-16 3 views
9
public static void main(String[] args) { 

    List<? extends Object> mylist = new ArrayList<Object>(); 

    mylist.add("Java"); // compile error 

} 

Вышеупомянутый код не позволяет добавлять элементы в список, а дикие карты могут использоваться только как подпись в методах, опять же не для добавления, а только для доступа. В этом случае, какую цель выполняет вышеуказанное?Коллекции Java с использованием подстановочных знаков.

ответ

5

Допустим, у вас есть интерфейс и два класса:

interface IResult {} 
class AResult implements IResult {} 
class BResult implements IResult {} 

Тогда у вас есть классы, которые возвращают список в результате:

interface ITest<T extends IResult> { 
    List<T> getResult(); 
} 

class ATest implements ITest<AResult> { 
    // look, overridden! 
    List<AResult> getResult(); 
} 

class BTest implements ITest<BResult> { 
    // overridden again! 
    List<BResult> getResult(); 
} 

Это хорошее решение, когда вам нужно «ковариантном возвращает ", но вы возвращаете коллекции вместо своих собственных объектов. Большой плюс заключается в том, что вам не нужно бросать объекты при использовании ATest и BTest независимо от интерфейса ITest. Однако при использовании интерфейса ITest вы не можете добавить ничего в список, который был возвращен, поскольку вы не можете определить, какие типы объектов действительно содержит список! Если это будет разрешено, вы сможете добавить BResult в список <AResult> (возвращенный как Список <? Extends T >), что не имеет никакого смысла.

Итак, вы должны помнить об этом: Список <? extends X > определяет список, который можно легко переопределить, но который доступен только для чтения.

1

С использованием джокеров Java с использованием подстановочных знаков вы можете разрешить вышеуказанное объявление, считая, что вы только собираетесь его прочитать.

Вам не разрешено добавлять/писать на него, потому что все общие типы должны быть удалены во время компиляции, а во время компиляции не существует способа, которым компилятор знает, что List - это только строки (это может быть любое объект, включая строки!)

Вам, однако, разрешено читать от него, так как они будут как минимум объектами. Смешивание разных типов в коллекциях Java не допускается, чтобы вещи были чистыми и понятными, и это помогает обеспечить ее.

+0

Нет, это неправильно. По крайней мере, из второго абзаца объяснение не соответствует теме. Дело не в стирании стилей. – jrudolph 2008-09-16 07:55:15

+0

Первый абзац тоже не прав. Вы можете удалить или добавить null в список, как указано в вопросе, вы также можете добавить (не нулевые) ссылки, если подстановочный знак определен с суперсвязью. – 2008-09-16 18:48:30

1

Точка ограниченных типов подстановок - их использование в сигнатурах методов для повышения гибкости API. Если, например, вы реализуете общий Stack<E>, вы могли бы обеспечить способ подтолкнуть ряд элементов стека следующим образом:

public void pushAll(Iterable<? extends E> elements) { 
    for(E element : elements){ 
     push(e); 
    } 
} 

По сравнению с pushAll(Iterable<E> elements) подписи без шаблона, это имеет то преимущество, что его позволяет передавать подтипы E методу - обычно это не допускается, так как Iterable<String> является несколько противоречивым, а не подклассом Iterable<Object>.

0

Это работает:

List<? super Object> mylist = new ArrayList<Object>(); 
mylist.add("Java"); // no compile error 

От Java Generics О'Рейли:

Командлет Get и положить принцип: использовать подстановочные распространяется, когда вы получите только значения нашей структуры, использовать супер подстановочные когда вы только ставите значения в структуру и не используете подстановочный знак, который вы оба получаете и ставите.

5

В своей книге «Эффективная Java» (второе издание) Джошуа Блох объясняет, что он называет принципом производителя/потребителя для использования дженериков. Джош объяснения должны сказать вам, почему ваш пример не работает (компилировать) ...

Глава 5 (дженерик) находится в свободном доступе здесь: http://java.sun.com/docs/books/effective/generics.pdf

Более подробная информации о книге (и авторе) доступна: http://java.sun.com/docs/books/effective/

0

List<? extends Object>, который является таким же, как List<?>, выполняет назначение обобщающего вся типы List<String>, List<Number>, List<Object> и т.д. (так что все тип с надлежащим типом в месте ?). Значения всех этих типов могут быть присвоены переменной типа List<?> (где она отличается от List<Object>!).

В общем, вы не можете добавить строку в такой список. Однако вы можете прочитать Object из списка, и вы можете добавить к нему null. Вы также можете рассчитать длину списка и т. Д. Это операции, которые гарантируют работу для каждого из этих типов.

Для ознакомления с условными обозначениями, см. Документ Adding Wildcards to the Java Programming Language. Это академический документ, но все еще очень доступный.

0

Java Дженерики: Дикие карты в коллекциях

  1. расширяет
  2. супер
  3. ?

Сегодня я собираюсь объяснить вам, как полезные карты полезны. Понять эту концепцию немного сложно

Теперь предположим, что у вас есть абстрактный класс и у вас есть абстрактный метод под названием paintObject().

Now you want to use different type of collection in every child class. 

Это ниже AbstractMain Method.

Вот шаги, которые мы предприняли для этого Аннотация Основного метода

1. Мы создали абстрактный класс

2. в параметре мы должны определить Т (вы можете использовать любой символ) - В этом случае, какой бы класс не реализовал этот метод, он может использовать любой тип класса. ex. Класс может реализовать метод, как общественного ничтожной paintObject (объект ArrayList) или общественный недействительный paintObject (объект HashSet)

3. И мы также использовали E расширяет MainColorTO - В этом случае Е распространяется MainColorTo - Это явно означает, какой класс вы хотите использовать, который должен быть подклассом MainColorTo

4. Мы определим абстрактный метод, называемый paintObject (T объект, E objectTO) --Now здесь какой класс реализации метод, метод может использовать любой класс по первому аргументу и второго параметра, метод должен использовать тип из MainColorTO

public abstract class AbstractMain<T,E extends MainColorTO> { 
     public abstract void paintObject(T Object,E TO); 
} 

Теперь мы продолжим рассмотрение абстрактного класса и реализуем метод ниже класса ex.

public class MainColorTO { 
    public void paintColor(){ 
      System.out.println("Paint Color........"); 
    } 
    } 

public class RedTO extends MainColorTO { 
    @Override 
    public void paintColor() { 
    System.out.println("RedTO......"); 
} 
} 
public class WhiteTO extends MainColorTO { 
    @Override 
    public void paintColor() { 
    System.out.println("White TO......"); 
    } 
} 

Теперь мы возьмем два примера.

1.PaintHome.java

public class PaintHome extends AbstractMain<ArrayList, RedTO> { 
    @Override 
    public void paintObject(ArrayList arrayList,RedTO red) { 
     System.out.println(arrayList); 

    } 
} 

Теперь в выше PaintHome.java вы можете проверить, что мы использовали ArrayList в первом аргументе (Как мы можем взять любой класс), а во втором аргументе мы использовали RedTO (который расширяет MainColorTO)

2.PaintCar.java

public class PaintCar extends AbstractMain<HashSet, WhiteTO>{ 
    @Override 
    public void paintObject(HashSet Object,WhiteTO white) { 
     System.out.println(Object); 

    } 
} 

Теперь в выше PaintCar.java вы можете проверить, что мы использовали HashSet в первом аргументе (Как мы можем взять любой класс), а во втором аргументе мы использовали WhiteTO (расширяющее MainColorTO)

Ponint Помнить вы не можете использовать супер ключевое слово на уровне класса можно использовать только ключевое слово проходит на уровне класса Defination

public abstract class AbstractMain<P,E super MainColorTO> { 

    public abstract void paintObject(P Object,E TO); 

} 

выше код даст вам компилятора об ошибке.

Смежные вопросы