2012-06-07 2 views
2

Когда я пытаюсь скомпилировать это:Несовместимые типы - SortedSet и TreeSet

import java.util.*; 

public class NameIndex 
{ 
    private SortedMap<String,SortedSet<Integer>> table; 

    public NameIndex() 
    { 
     this.table = new TreeMap<String,TreeSet<Integer>>(); 
    } 
} 

я получаю:

Incompatible types - found java.util.TreeMap<java.lang.String,java.util.TreeSet<java.lang.Integer>> but expected java.util.String,java.util.SortedSet<java.lang.Integer>> 

Любая идея, почему?

UPDATE: компилируется:

public class NameIndex 
{ 
    private SortedMap<String,TreeSet<Integer>> table; 

    public NameIndex() 
    { 
     this.table = new TreeMap<String,TreeSet<Integer>>(); 
    } 
} 
+0

возможно дубликат [Is 'Список ' подкласс 'Список '? Почему не генерические роды Java неявно полиморфны?] (Http://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-arent-javas-generics-implicit) – assylias

+0

Да - взятие Посмотрите на этот вопрос. Думаю, я согласен. Мое понимание состоит в том, что, читая этот вопрос, вы не можете иметь один общий интерфейс, а другой общий - как конкретный класс. Они должны быть одинаковыми. – Snowcrash

ответ

2

Попробуйте это:

this.table = new TreeMap<String, SortedSet<Integer>>(); 

Вы можете указать фактического типа значений в карте, когда вы добавляете элементы к ней, тем временем вы должны использовать те же типы, которые использовались во время объявления атрибута (а именно String и SortedSet<Integer>).

Например, это будет работать при добавлении новых пар ключ/значение к карте:

table.put("key", new TreeSet<Integer>()); 
1

Всегда введите объект с интерфейсом вместо конкретного типа. Поэтому у вас должно быть:

private Map<String, Set<Integer>> table; 

вместо того, что у вас есть прямо сейчас. Преимущество состоит в том, что вы можете отключать реализации, когда захотите.

Тогда:

this.table = new TreeMap<String, Set<Integer>>(); 

Вы получаете ошибку во время компиляции, потому что SortedSet и TreeSet различные типы, хотя они реализуют один и тот же интерфейс (Set).

+0

SortedSet - это интерфейс, поэтому я использовал его в объявлении таблицы. Затем я предполагал использовать конкретный тип (например, TreeSet) для реализации. Но это не скомпилировалось. Итак, я должен был указать конкретный тип (т. Е. TreeSet) оба раза. Это то, что меня смущает. – Snowcrash

+0

Ошибка времени компиляции вызвала генерики, а не внешние типы. 'TreeMap' является допустимым подтипом (реализацией)' SortedMap'. – CheeseWarlock

+0

@CheeseWarlock Вы правы. Я перепутал карту и набор. Закрепление. –

1

Вы всегда можете заявить:

private SortedMap<String, ? extends SortedSet<Integer>> table; 

, но я предлагаю использовать:

private Map<String, ? extends Set<Integer>> table; // or without '? extends' 

Посмотрите на this вопрос

+0

Я бы предложил '? extends SortedSet ', поскольку в исходной записи в вопросе предполагается, что внутренний набор является' TreeSet' не только набором. –

+0

Я считаю, что 'SortedSet' и' Set' являются обоими интерфейсами, поэтому, объявляя '? extends SortedSet' Я думаю, вы не станете компрометировать принцип программирования для интерфейсов, а не для реализации. Кроме того, контракт для 'SortedSet' отличается от договора' Set', и он имеет несколько дополнительных методов, доступных в его открытом интерфейсе, недоступных в простой 'Set'. –

+0

@edalorzo Я полностью согласен с вами. Предоставление 'SortedSet' в декларации зависит от того, как он будет использовать это поле позже. – Xeon

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