用Java实现多种泛型类型的抽象泛型方法

时间:2012-12-22 22:45:13

标签: java generics parameters

我会问一个非常简短的问题,并希望有人可以帮助我找到解决方案。它涉及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

嗯,就是这种情况。 在此先感谢所有人! 希望将来能帮助别人!

P.D:这不是枚举类型的问题..它发生在类层次结构中。所以不要理会责备emuns ......我试过这个,但也不行。

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 extends String)。

对于Generics返回类型

使用特定返回类型覆盖泛型方法没有问题,只要返回类型是覆盖返回类型的子类型。首先是什么样的返回类型?好吧,它碰巧是对象。默认情况下,编译器假定(在方法签名中)泛型类型为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();
}

感谢所有帮助解决这个问题的人!

2 个答案:

答案 0 :(得分:11)

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());

答案 1 :(得分:4)

完成JB Nizet的answer时,写下:

<K>

隐含地意味着:

<K extends Object>

该方法必须接受任何对象。将其限制为子类上的DesiredClass实际上不会覆盖任何内容,如错误消息所示。

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

修改:实际上正如评论中所讨论的那样,String public foo();会有效地覆盖Object public foo();