11

它是关于 java 中具有两种泛型类型(一种用于返回类型,另一种用于形式参数)的泛型方法以及如何实现它。我想我在图片中遗漏了一些东西来让它工作。

事情是这样的...

这是有效的:

public enum Getter
{
    BillItemsSize {
        @Override
        public Integer get (Object entity) {
            DesiredClass ref = (DesiredClass ) entity; // "Old time" cast
            // do things...
        }
    };

    public abstract <T,K> T get (K entity);        
}

不起作用

public enum Getter
{
    BillItemsSize {
        @Override
        public Integer get (DesiredClass entity) { // no cast at all
            // do things
        }
    };

    public abstract <T,K> T get (K entity);        
}

java编译器对我大喊:

<anonymous datasource.db.Getter$1> is not abstract and does not override abstract method <T,K>get(K) in Getter

嗯,情况就是这样。在此先感谢大家!希望它在未来对其他人有所帮助!

PD:这不是枚举类型的问题。它发生在类层次结构中。所以不要费心去责怪枚举,我试过这个但不起作用。

public abstract class SuperClass
{
    public abstract <T,E> T pepe (E e);
}

public class SubClass extends SuperClass
{

    @Override
    public Integer pepe(DesiredClass e) // fails... 
    {
        return null;
    }
    
}

更新:

对于泛型参数

我们可以制定一个通用规则声明,对于“泛型参数”(其类型是泛型的),方法签名中隐式采用的类型等于该泛型的上限,如果没有指定,则可以是 Object,或者更多如果使用上限,则为特定子类(例如 T 扩展字符串)。

对于泛型返回类型

用特定返回类型覆盖泛型方法没有问题,只要返回类型是被覆盖返回类型的子类型。首先返回类型是什么?好吧,它恰好是对象。默认情况下,编译器假定(在方法签名中)泛型类型为 Object 类型。

所以我们必须知道,诀窍是知道任何具有泛型返回类型的方法实际上都具有Object返回类型。然后,如果在任何子类中该方法被覆盖并且我们更改他的返回类型,说明返回另一种类型,则不会有问题。因为,除了该方法将返回另一个类的对象之外,返回的对象将不可避免地是 Object 类的子类,并且只要它是原始的子类型,覆盖具有不同返回类型的方法就没有问题。 . 称为协变返回类型的技术允许我们做这样的事情。

public abstract class SuperClass
{
    public abstract <T> T operation ();
}


public class SubClass extends SuperClass
{

    @Override
    public Chair operation()
    {
        //bla bla 
    }
    
}   

同时在代码的另一部分......

void main ()
{
        SubClass sb = new SubClass();
        Chair chair = sb.operation ();
        // the chair type can be easely replaced by super type (like Object)
        Object object = sb.operation();
}

感谢所有帮助清除此问题的人!

4

2 回答 2

14
public abstract <T,K> T get (K entity);        

是一种可以将任何内容作为参数的方法,并且可以返回任何内容。

用它覆盖它

public Integer get (DesiredClass entity)

不起作用,因为您将可以传递给方法的参数类型限制为 DesiredClass,从而打破了 Liskov 原则。

没有泛型会更容易理解。假设您在 Bar 类中有一个抽象方法:

public abstract void fillRecipient(Recipient r);

然后你尝试在 SubBar 中覆盖它

public void fillRecipient(Glass glass) {
}

如果上面的代码是合法的,下面的代码会做什么?

Bar bar = new SubBar();
bar.fillRecipient(new Mug());
于 2012-12-22T22:53:19.830 回答
4

为了完成 JB Nizet 的回答,当您编写时:

<K>

它隐含的意思是:

<K extends Object>

该方法必须接受任何对象。将其限制DesiredClass在子类上实际上不会覆盖任何内容,就像错误消息所说的那样。

被覆盖的方法必须具有完全相同的签名,不允许在参数或返回类型中使用子/超类型。

编辑:实际上正如评论中所讨论的那样,String public foo();有效地覆盖了Object public foo();.

于 2012-12-22T23:03:00.890 回答