是否可以使用泛型返回类型定义接口方法,并且具体实现定义返回类型?

时间:2011-09-15 15:18:05

标签: java generics

我想创建一个界面:

public interface OperandValue
{
    <T> T getValue();
}

我希望有一个这样的具体实现:

public class NumberOperandValue implements OperandValue
{
    @Override
    public <Integer> Integer getValue()
    {
        // some integer value that is set elsewhere
        return 1;
    }
}

Eclipse强调<Integer>给我一个警告:

  

类型参数Integer隐藏了Integer类型

我感谢任何关于这是否能以某种方式起作用的建议。我意识到我可以在接口级别而不是方法级别定义泛型类型,但是如果可能的话,我想尝试使其工作。

1 个答案:

答案 0 :(得分:23)

您可能希望将界面更改为:

public interface OperandValue<T>
{
    T getValue();
}

执行到:

public class NumberOperandValue implements OperandValue<Integer>
{
    @Override
    public Integer getValue()
    {
        // some integer value that is set elsewhere
        return 1;
    }
}

现在,您告诉接口您希望该方法返回什么类型。换句话说,您将接口类型设为泛型,而不是方法声明。但这似乎就是你想要的。

作为旁注:

public <Integer> Integer getValue()

实际上意味着'定义一个名为“Integer”的泛型类型参数,其中getValue返回刚刚定义的“整数”类型。

回应史蒂夫的评论

  

当我从我的方法实现中删除<Integer>时   收到一条警告:Type safety: The return type Integer for getValue() from the type NumberOperandValue needs unchecked conversion to conform to T from the type OperandValue

该警告消息表明您在使用Java泛型时违反了规则。要了解原因,请在删除<Integer>类型参数之前考虑方法签名的含义。

public <Integer> Integer getValue()

此签名表示方法getValue返回类型Integer的值,其中Integer被定义为您在尖括号之间定义的泛型类型参数。字符串Integer的含义完全是任意的,其含义与:

完全相同
public <T> T getValue()

为清楚起见,为了您的问题,我们坚持使用此版本的方法签名。删除类型参数后会发生什么?

public T getValue()

现在,如果您尝试编译,则会收到T未定义的错误。但是,因为您的原始类型签名声明了名称为Integer的type参数,所以当您删除它时,您将被留下:

public Integer getValue()

由于Integer 已经是预定义类型,因此方法签名在技术上仍然合法。但是,类型参数的名称恰好与已存在的类型相同,这只是一个意外。

此外,因为您的接口已经使用泛型声明了方法签名,所以当您从实现中删除它时,Java编译器会生成警告。具体来说,编译器担心在基类中,方法的返回类型是(类型擦除到Object)通用参数,名为Integer,它不是同一类型(也不是已知类型兼容的)系统类名为Integer(或准确地称为java.lang.Integer)。