实现java接口并使用泛型

时间:2013-10-07 16:03:17

标签: java generics interface

我有一个名为BST的java接口(二进制搜索树的简称),它有通用类型Key,Value,其中Key扩展为Comparable。我将其定义如下。

public interface BST<Key extends Comparable<Key>,Value> {

    public void put(Key key,Value value);

    public Value get(Key key);

    public void delete(Key key);

    public Iterable<Key> keys();

}

现在我想定义上述接口的实现。我试过这个

public class BSTImpl<Key extends Comparable<Key> ,Value>  implements BST<Key extends Comparable<Key>,Value> {

... 

}

以上定义在eclipse IDE中导致错误消息。extends之后的implements BST<Key令牌似乎是罪魁祸首

  

令牌“extends”的语法错误,预期

如果我从定义中省略了“extends”标记(如下所示),则错误消失,我可以通过eclipse正确生成未实现的方法

public class BSTImpl<Key extends Comparable<Key> ,Value>  implements BST<Key ,Value> {
    @Override
    public void put(Key key, Value value) {
        // TODO Auto-generated method stub          
    }
    @Override
    public Value get(Key key) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public void delete(Key key) {
        // TODO Auto-generated method stub          
    }
    @Override
    public Iterable<Key> keys() {
        // TODO Auto-generated method stub
        return null;
    }
}

为什么extends token首先会导致错误?有人可以解释一下吗?

3 个答案:

答案 0 :(得分:5)

由于

public class BSTImpl<Key extends Comparable<Key> ,Value>  implements BST<Key extends Comparable<Key>,Value> {
                    ^ type declaration                                   ^ type argument

在类声明中,泛型类型是一个类型声明,您可以稍后在类体中重用它。在您正在实现的接口中,它是一个类型参数参数。换句话说,您说我的类使用此类型实现此接口。你必须给它一个特定的类型。将Key extends Comparable...称为类型参数是没有意义的。

Java Language Spec has more details

  

类型参数部分在类名后面,并由分隔符组成   尖括号。

the section for Superclasses

  

如果TypeDeclSpecifier后跟任何类型参数,则必须是   正确调用由表示的类型声明   TypeDeclSpecifier,并且所有类型参数都不是通配符类型   参数,或发生编译时错误。

答案 1 :(得分:1)

另一个答案是正确的,但我只是想添加修复

基本上,您将类型参数传递给超类/接口,如下所示:

public class BSTImpl<Key extends Comparable<Key>, Value> implements BST<Key, Value> {
    ... 
}

另外请遵守java命名标准,并为您的通用参数宝贝使用单个字母。使用单词很容易与作为类名混淆。

答案 2 :(得分:1)

关键字extendssuper定义泛型类型的约束。只有在 中约束类型参数才有意义,而不是 out 的类型参数。

情况类似于方法参数。声明方法时,使用:

public void foo(Bar bar) { 
    //          ^ the type is a constraint on bar 
}

(“约束”是传递给bar的任何值必须是Bar或其子类型之一。)

但是,您只需使用以下方法调用该方法:

foo(someBar);
//  ^ no constraint specified here

也就是说,限制使用它的变量的类型是没有意义的。 (这已在声明中完成。)

在你的类声明中,它更令人困惑,因为声明了泛型类型,并且在同一行上使用了另一个类型。该行的解释是:

class BSTImpl<Key extends Comparable<Key>, Value>
//                ^ a constraint on the types that can be passed to Key
    implements BST<Key, Value>
//                 ^ here we're passing Key to another generic type

当然,就像变量一样,Key的传入“类型”必须与使用它所需的类型兼容,这就是为什么你必须复制声明中的约束< / {>的BSTImpl

(这种对称性也说明了泛型的真正含义:它们是高阶类型约束,这是指定“类型类型”的一种方式。)