Почему это перечисление не компилируется? - PullRequest
2 голосов
/ 01 марта 2011

Почему это перечисление не компилируется?

public enum Ackr implements Cloneable{
    INSTANCE;

    public <Ackr extends Cloneable> Ackr getInstance(){
        return INSTANCE; //Type mismatch: cannot convert from Ackr to Ackr
//      return (Ackr)INSTANCE; //Type safety: Unchecked cast from Ackr to Ackr
    }
}

Ответы [ 4 ]

4 голосов
/ 01 марта 2011

Этот тип аргумента, насколько я знаю, не является обязательным. Попробуйте просто

public Ackr getInstance(){
    return INSTANCE;
}
2 голосов
/ 01 марта 2011

Я вижу, что у вас неправильное представление о дженериках. Класс enum Ackr отличается от типа <Ackr extends Cloneable.

public <Ackr extends Cloneable> Ackr getInstance()

Вы определяете новый тип с помощью описанного выше метода. Это полностью отличается от enum класса Ackr. Вот почему ваш класс не может быть скомпилирован.

2 голосов
/ 01 марта 2011

Чего вы пытаетесь добиться с помощью этой подписи?

public <Ackr extends Cloneable> Ackr getInstance() ...

Не могли бы вы просто написать это?

public Ackr getInstance() ...

Я также думаю, что enumэто расширяет Clonable отчасти бессмысленно.enum не может быть скопировано ... существует только одно значение перечисления.

1 голос
/ 01 марта 2011

Вы написали в комментарии:

Я думаю, что нет причины для <Ackr extends Cloneable>, но в каком контексте эта конструкция будет иметь смысл?

Этопараметр типа для вашего метода.

public <Ackr extends Cloneable> Ackr getInstance(){ ... }

определяет метод, который возвращает объект некоторого типа (выбираемый вызывающей стороной), который расширяет Cloneable.Этот метод может только легально вернуть null (поскольку у вас нет способа узнать, какой тип выбрал вызывающий объект, а null является единственным значением, общим для всех ссылочных типов), или выдать исключение, поэтому он не очень полезен.

Параметр типа Ackr здесь не имеет отношения к вашему перечисляемому классу с тем же именем, поэтому вам лучше написать его так:

public <A extends Cloneable> A getInstance(){ ... }

В Java API есть несколько примеров, которыеесть такие варианты использования параметров типа, которые используются только в возвращаемом типе, но затем они возвращают некоторый параметризованный тип (а параметр типа метода используется в качестве параметра типа для возвращаемого типа).Ищите, например, Collections.emptySet().

Чаще всего параметры типа метода используются в типах параметров метода (только или дополнительно к возвращаемому типу).

 public <A> A getFirstElement(Iterable<A> list);

Этот метод принимает Iterable некоторого типа A и возвращает объект этого типа A. (Из названия можно было бы предположить, что он берет первый элемент этого итерируемого.) Вот реализация:

 public <A> A getFirstElement(Iterable<A> list) {
     Iterator<A> it = list.iterator();
     if(it.hasNext()) {
         return it.next();
     }
     return null;
 }

Обычно: Если у вас есть параметр типа (где-либо), убедитесь, что вы не называете его так же, как какой-либо существующий тип (как вы сделали здесь) - он будет затенять ваш существующий тип, приводяк большой путанице из-за странных сообщений об ошибках, таких как Ackr не может быть назначен Ackr .

По этой причине параметры типа причины часто имеют одно (или редко два) имен символов, таких как E (элемент-тип), K, V (тип ключа и значения для карт), T (тип в целом).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...