public abstract class AbstractEntity
{
private int id;
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
}
public class Entities extends Hashtable<Integer, AbstractEntity>
{
}
public abstract class AbstractManager<T extends Entities, V extends AbstractEntity>
{
protected T entities;
public V get(int id)
throws NoSuchEntityException
{
V e = (V)entities.get(id);
if (e != null)
return e;
else
throw new NoSuchEntityException();
}
}
IDE показывает unchecked cast в классе AbstractManager в методе get на строке
V e = (V)entities.get(id);
Почему? Ведь явно показано что V есть наследник от AbstractEntity, entities.get(id) возвращает именно AbstractEntity. Если сделать так:
V e = entities.get(id);
то это будет ошибкой приведения типов (требуется V, найден AbstractEntity)
Почему так происходит?
И правильно ли я понимаю, что в рантайме нельзя создавать объект параметрического типа, т.е. мне придется инициализировать поле entities вне класса AbstractManager?
M>public abstract class AbstractManager<T extends Entities, V extends AbstractEntity> M>{ M> protected T entities;
M> public V get(int id) M> throws NoSuchEntityException M> { M> V e = (V)entities.get(id);
M> if (e != null) M> return e; M> else M> throw new NoSuchEntityException(); M> } M>}
M>то это будет ошибкой приведения типов (требуется V, найден AbstractEntity)
M>Почему так происходит?
M>И правильно ли я понимаю, что в рантайме нельзя создавать объект параметрического типа, т.е. мне придется инициализировать поле entities вне класса AbstractManager?
M>Спасибо.
Во первых форматирование!!!
Во вторых не понятно зачем такой огород, если можно написать так.
public abstract class AbstractManager<V extends AbstractEntity> {
protected Map<Integer, V> entities = new HashMap<Integer, V>();
public V get(int id) throws NoSuchEntityException {
V e = (V) entities.get(id);
if (e != null)
return e;
else
throw new NoSuchEntityException();
}
}
На твой вопрос скажу, что нет. В рантайме создавать параметризованный тип нельзя. Их и нет в рантайме. Параметризация сучествует только на уровне компиляции. Почитай про особенности реализации Generics в java. Ключевое слово затирание (erasure).
package ru.rsdn.generics;
import java.util.Hashtable;
public abstract class AbstractManager<T extends Hashtable<Integer, V>, V extends AbstractEntity> {
protected T entities;
public V get(int id) throws NoSuchEntityException {
V e = entities.get(id);
if (e != null)
return e;
else
throw new NoSuchEntityException();
}
}
Небольшой рефакторинг и все работает.
M>Почему так происходит?
А вы проведите простой эксперимент:
package ru.rsdn;
public class A {
}
package ru.rsdn;
public class B extends A {
}
package ru.rsdn;
public class Test {
public static void main(String[] args) {
B b = new A(); // compile error: can't convert A to B
}
}
Намек понятен?
В вашем коде аналогично: попытка приведения базового класса к наследнику.
M>И правильно ли я понимаю, что в рантайме нельзя создавать объект параметрического типа, т.е. мне придется инициализировать поле entities вне класса AbstractManager?
Да, экземпляр обобщенного типа Java нельзя создать внутри класса, который по нему параметризован, только извне.
package ru.rsdn.generics;
import java.util.Hashtable;
public abstract class AbstractManager<T extends Hashtable<Integer, V>, V extends AbstractEntity> {
protected T entities;
public V get(int id) throws NoSuchEntityException {
if (entities.containsKey(id))
return entities.get(id);
throw new NoSuchEntityException();
}
}
Здравствуйте, manenkov, Вы писали:
M>что не так с синтаксисом объявления класса
Параметризацию проводят в объявлении, а вы пытаетесь сделать в подстановке — и не совсем понятно зачем. Наверно хотели что-то вроде этого:
public class Entities<T extends AbstractEntity> extends Hashtable<Integer, T>
Здравствуйте, stenkil, Вы писали:
S>Похоже придется учитывать и IDE
Скорее всего просто настройки компилятора в IDE — предупреждения попросту можно отключить.
Здравствуйте, rsn81, Вы писали:
R>Здравствуйте, stenkil, Вы писали:
S>>Похоже придется учитывать и IDE R>Скорее всего просто настройки компилятора в IDE — предупреждения попросту можно отключить.
Но, наверное, все-таки не нужно. Можно использовать @SuppressWarnings
Здравствуйте, LeonidV, Вы писали:
LV>Но, наверное, все-таки не нужно.
А разве предлагал? Просто предположил, что в JDeveloper-е умолчальные настройки компилятора такие.
LV> Можно использовать @SuppressWarnings
Каюсь, использую, стараюсь пореже.