Исключить параметр типа java generics

Код:

interface Property<T>
{
    T get();
}

class BoolProperty implements Property<Boolean>
{
    @Override
    public Boolean get()
    {
        return false;
    }
}
class StringProperty implements Property<String>
{
    @Override
    public String get()
    {
        return "hello";
    }
}
class OtherStringProperty implements Property<String>
{
    @Override
    public String get()
    {
        return "bye";
    }
    public String getSpecialValue()
    {
        return "you are special";
    }
}

используется моим классом:

class Result<P extends Property<X>, X>
{
    P p;
    List<X> list;
}

Как видите, он имеет два типа параметров P и X. Несмотря на это, X всегда можно вывести из P, но для этого языка я должен предоставить оба:

Result<BooleanProperty, Boolean> res = new Result<BooleanProperty, Boolean>();

Есть ли какой-либо трюк, чтобы избавиться от параметра типа X? Я хочу просто использовать

Result<BooleanProperty> res = new Result<BooleanProperty>();

Кроме того, я не хочу потерять информацию о типе и использовать ее как:

Result<OtherStringProperty> res = new Result<OtherStringProperty>();
String spec = res.p.getSpecialValue();
String prop = res.list.get(0);

Ответ 1

Есть аналогичный вопрос, ответ на который вы можете найти интересным: fooobar.com/questions/16053/...

По сути, нет никакого реального способа обойти, включая дополнительный родовой тип, потому что компилятор не может знать, какой тип вы используете без него. Я предполагаю, что это побеждает цель вашего подхода, но вы можете попробовать расширить Result при указании типов - что-то вроде этого:

class BoolResult extends Result<BoolProperty, Boolean> {
    // Do stuff
}

Ответ 2

Я бы изменил класс Result на что-то вроде

class Result<X> {
    Property<X> property;
    List<X> list;
}

Я не думаю, что компилятор может вывести X из Property, так как ваш класс Result ждет два определения для двух генериков.

Ответ 3

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

class BoolProperty implements Property<Boolean>
{
    @Override
    public Boolean get()
    {
        return false;
    }
}

class Sub<X, P extends Property<X>> {
    P p;
    List<X> list;
}

class Result<X> extends Sub<X, Property<X>> {
}

Result<Boolean> res = new Result<Boolean>();
List<Boolean> list = res.list;
Boolean b = res.p.get();
List<String> res2 = res.list; // compilation error

Ответ 4

Пробовали ли вы использовать общий шаблон?

class Result<? extends Property<X>>
{
    // stuff
}