2013-09-23 5 views
0

У меня есть класс с использованием карты в качестве переменного поля:Java шаблоны и общие методы

private Map<String, ?> posts; 

И в этом же классе у меня есть универсальный метод:

public <T> void log(T message) { 
    if (isEnabled) { 
     Date time = Calendar.getInstance().getTime(); 
     SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss:SS"); 
     posts.put(sdf.format(time.getTime()), message); 
    } 
} 

Однако я получаю ошибку компиляции на высказывании posts.put заявления:

The method put(String, capture#2-of ?) in the type Map<String,capture#2-of ?> is not 
applicable for the arguments (String, T) 

Я немного новичка в подстановочные знаки и общие методы, так что я делаю не так?

+1

Должности должны быть 'private Map сообщений;' как вы знаете, что он содержит элементы T. – agad

+2

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

ответ

4

Map<String, ?> не означает, что вы можете поставить что-нибудь в эту карту. Это означает, что класс значения неизвестен. Но это может быть, например, Foo или Bar. И Foo может быть несовместим с любым типом T, поэтому компилятор жалуется. Используйте Map<String, Object> вместо или сделать свой T параметр на уровне класса, а затем параметризуем карту с ним: Map<String, T>

4

Когда вы объявить Map с неограниченным типа подстановочных:

private Map<String, ?> posts; 

вы не сможете поставить ничего, кроме null. Потому что ? является заменой для любого типа. В принципе, ваш Map является супертипом всего экземпляра Map с String в качестве ключа и значения любого типа. ? может быть Дата, Номер, Cat, Tiger, что угодно.

Предположим, что ваша карта конкретизируется следующим образом:

private Map<String, ?> posts = new HashMap<String, Date>(); 

и параметр типа в методе выводится в String, то ваш метод put делает:

posts.put(String, String); 

... пытаясь таким образом добавить String тип, где требуется Date. Конечно, это не удастся во время выполнения. Общий тип позволяет избежать этой проблемы, выпуская для этого ошибку компилятора.


Вы можете решить эту проблему, сделав сам ваш класс универсальным, таким образом, используя один и тот же параметр типа в методе и карты:

class YourClass<T> { 
    private Map<String, T> posts; 

    public void log(T message) { 
     if (isEnabled) { 
      Date time = Calendar.getInstance().getTime(); 
      SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss:SS"); 
      posts.put(sdf.format(time.getTime()), message); 
     } 
    } 
} 

Кроме того, как отмечено в комментариях, вы должны избегать есть time как ключ. Поскольку Date#getTime() имеет точность только в миллисекундах, то все, что вы помещаете в течение интервала, которое покрывается за один миллисекунды, будет храниться в виде одного и того же ключа, таким образом перезаписав старое значение этого ключа.

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