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

Ste*_*eve 14 java generics

我想创建一个接口:

public interface OperandValue
{
    <T> T getValue();
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

类型参数Integer隐藏了Integer类型

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

Kir*_*oll 26

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

public interface OperandValue<T>
{
    T getValue();
}
Run Code Online (Sandbox Code Playgroud)

并实施:

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

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

作为旁注:

public <Integer> Integer getValue()
Run Code Online (Sandbox Code Playgroud)

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

回应史蒂夫的评论如下:

当我<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>type参数之前考虑方法签名的含义.

public <Integer> Integer getValue()
Run Code Online (Sandbox Code Playgroud)

此签名表示该方法getValue返回type的值,Integer其中where Integer值定义为您在尖括号之间定义的泛型类型参数.字符串的含义Integer完全是任意的,具有与以下内容完全相同的含义:

public <T> T getValue()
Run Code Online (Sandbox Code Playgroud)

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

public T getValue()
Run Code Online (Sandbox Code Playgroud)

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

public Integer getValue()
Run Code Online (Sandbox Code Playgroud)

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

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

  • @Kal,是的,这是可能的。但是不可能在实现类中“插入”特定类型。如果该方法是泛型的,则意味着该方法的 *caller* 负责提供类型参数。 (2认同)