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

2022-09-01 20:23:18

我想创建一个接口:

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

您可能希望将接口更改为:

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“的泛型类型参数,其中返回刚刚定义的”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 泛型时违反了规则。为了了解原因,让我们在删除 type 参数之前考虑方法签名的含义。<Integer>

public <Integer> Integer getValue()

此签名意味着该方法返回一个类型的值,其中定义为在尖括号之间定义的泛型类型参数。字符串的含义是完全任意的,并且具有与以下完全相同的含义:getValueIntegerIntegerInteger

public <T> T getValue()

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

public T getValue()

现在,如果您尝试编译,则会收到未定义的错误。但是,由于原始类型签名声明了带有 name 的 type 参数,因此在删除该参数时,您只能使用:TInteger

public Integer getValue()

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

此外,由于您的接口已经使用泛型声明了方法签名,因此当您从实现中删除它时,Java 编译器会生成警告。具体来说,编译器关注的是,在基类中,方法的返回类型是名为 的泛型参数(类型擦除为),该参数与命名的系统类的类型不同(也不知道类型兼容)。ObjectIntegerIntegerjava.lang.Integer


答案 2

推荐