首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java泛型。为什么要编译它?

Java泛型。为什么要编译它?
EN

Stack Overflow用户
提问于 2011-09-26 21:14:22
回答 4查看 633关注 0票数 13
代码语言:javascript
复制
abstract class Type<K extends Number> {
    abstract <K> void use1(Type<K> k);           // Compiler error (Type parameter K is not within its bounds)
    abstract <K> void use2(Type<? extends K> k); // fine
    abstract <K> void use3(Type<? super K> k);   // fine
}

方法泛型类型K隐藏了类泛型类型K,因此<K>use1()中的<K extends Number>不匹配。.The编译器不知道有关use2()use3()中新泛型类型<K>的任何有用信息,但编译它仍然是合法的。为什么<? extends K> (或<? super K>)与<K extends Number>匹配

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-09-26 21:57:37

首先,让我们重写它,以避免阴影:

代码语言:javascript
复制
abstract class Type<N extends Number> {
    abstract <K> void use1(Type<K> k); 
    abstract <K> void use2(Type<? extends K> k); 
    abstract <K> void use3(Type<? super K> k);   
}

在第一个方法中,K作为Type<N extends Number>的类型参数,因此它的值应该符合TypeN的界限。但是,方法声明对K的值没有任何限制,因此它是非法的。如果您在K上添加必要的限制,则它是合法的

代码语言:javascript
复制
abstract <K extends Number> void use1(Type<K> k);

在下面的方法中,Type的实际类型参数是未知的(?),并且K对其施加了额外的限制,因此这些声明中没有任何非法的东西。

下面是一个具有类似声明的更实际的示例:

代码语言:javascript
复制
class MyList<N extends Number> extends ArrayList<N> {}

<K> void add1(MyList<K> a, K b) {
     a.add(b); // Given the method declaration, this line is legal, but it 
          // violates type safety, since object of an arbitrary type K can be
          // added to a list that expects Numbers
          // Thus, declaration of this method is illegal
}

<K> void add2(MyList<? extends K> a, K b) {
     // a.add(b) would be illegal inside this method, so that there is no way
     // to violate type safety here, therefore declaration of this method is legal
}

<K> void add3(MyLisy<? super K> a, K b) {
     a.add(b); // This line is legal, but it cannot violate type safey, since
          // you cannot pass a list that doesn't expect K into this method
}
票数 4
EN

Stack Overflow用户

发布于 2011-09-26 21:21:17

您遇到的问题是有两种K类型。如果您重命名一个,可能会更清楚。

代码语言:javascript
复制
abstract class Type<N extends Number> {
    abstract <K extends Number> void use1(Type<K> k); // fine
    abstract <K> void use2(Type<? extends K> k); // fine
    abstract <K> void use3(Type<? super K> k);   // fine
}

在某些情况下,你必须提供编译器可以推断的重复信息,在Java7中,它增加了一个<>菱形符号,告诉编译器去推断之前没有的类型。

来说明我的意思。下面是创建泛型类实例的不同方法。有些类型需要给定两次,而另一些则只需要一次。编译器可以推断类型。

一般而言,Java不会推断类型,而在大多数其他语言中可能会这样做。

代码语言:javascript
复制
class Type<N extends Number> {
    private final Class<N> nClass;

    Type(Class<N> nClass) {
        this.nClass = nClass;
    }

    static <N extends Number> Type<N> create(Class<N> nClass) {
        return new Type<N>(nClass);
    }

    static void main(String... args) {
      // N type is required.
      Type<Integer> t1 = new Type<Integer>(Integer.class);

      // N type inferred in Java 7.
      Type<Integer> t2 = new Type<>(Integer.class); 

      // type is optional
      Type<Integer> t3 = Type.<Integer>create(Integer.class); 

      // type is inferred
      Type<Integer> t4 = create(Integer.class);
    }
票数 9
EN

Stack Overflow用户

发布于 2011-09-26 21:20:40

当您像这样定义方法时:

代码语言:javascript
复制
abstract <K> void use1(Type<K> k);

有效地将类型K隐藏在类定义中。您应该能够像这样定义方法:

代码语言:javascript
复制
abstract void use1(Type<K> k);
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7555623

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档