【问题标题】:What makes a name of a generic type parameter, generic?是什么使泛型类型参数的名称泛型?
【发布时间】:2018-12-04 20:57:54
【问题描述】:

我正在为自己编写 Java 手册,我喜欢在其中加入可靠的事实。 我似乎无法描述泛型类型参数。我想知道什么名称显示为编译器的泛型类型而不是现有对象。我知道约定是字母“T”和其他单个字母。但我在 oracle.docs.com 中看到了一个类似的示例:

class name<T1, T2, ..., Tn>{}

所以现在我很困惑。为了让编译器将名称作为泛型类型参数,必须只有没有具有该名称的现有类吗? 如果我有一个班鲍比:

class Boby{ ... }

然后,如果我创建一个方法并将类的名称输入到 Bob 中:

void Method(Bob parameter){}

这是否只是编译和参数成为泛型类型?

【问题讨论】:

  • &lt;T1&gt;T1 声明为泛型参数(Java 语言规范中的类型变量),如果Bob 未声明为这样,它将不会被解释为一个(类似 到变量声明)。示例&lt;Bob&gt; void method(Bob parameter)
  • 你为什么不直接测试一下?对于一个泛型的方法,它必须声明它至少有一个泛型类型。为什么不尊重命名约定?这应该在您指南的最开始,早于泛型
  • 您可以查看 JLS(Java 语言规范),它定义了通用参数以及如何处理名称冲突。通常,泛型参数必须在 &lt;...&gt; 中声明,并且 IIRC 它优先于类名 - 这就是泛型类型通常命名为 TVT2 等的原因 - 因为类通常具有更长且更有意义名字。

标签: java generics


【解决方案1】:

任何名称都可以是泛型类型参数。如果您声明泛型类型参数Bob,并使用该名称而不是预期的类名称Boby,编译器会将其识别为泛型类型参数。

顺便说一句,如果你声明一个泛型类型参数Boby,它将隐藏类名Boby,因此在定义泛型类型参数的范围内(在整个类内或在单个方法)将引用泛型类型参数,而不是 Boby 类。

class Something<Bob> {
    void Method1(Bob parameter){} // refers to the generic type parameter Bob

    void Method2(Boby parameter){} // refers to the Boby class
}

class Something<Boby> {
    void Method(Boby parameter){} // refers to the generic type parameter Boby,
                                  // hiding the Boby class
}

class Something<T> {
    void Method(Bob parameter){} // compilation error - Bob is an undefined symbol
}

也就是说,为了使您的代码更具可读性,最好使用单个大写字母作为类型参数名称。

【讨论】:

  • 很好的解释谢谢。我把参数的概念弄错了。认为它们可以作为任何地方的非声明类型的参数大声笑,那将是一个童话:D
【解决方案2】:

类上声明的类型参数会影响任何实际类,就像本地类一样:

interface HasValue {
    int getValue();
}
class Foo {
}

class Bar implements HasValue {
    private int value;

    public Bar(int v) {
        this.value = v;
    }
    public int getValue() {
        return this.value;
    }
}

class Example<Foo extends HasValue> {
    public static final void main(String[] args) throws Exception {
        Example<Bar> e = new Example<>();
        e.method(new Bar(42));
    }

    public void method(Foo x) {
        System.out.println("x.getValue() is " + x.getValue());
    }
}

这很好用,因为在Example 中,Foo 是一个类型参数,而不是Foo 类。

【讨论】:

    【解决方案3】:

    要让编译器知道一个类是否用作泛型,您需要像这样指定它:

    public class MyClass<T> {}
    

    例如,如果您为列表创建泛型,我们假设如下:

    List<Bob> bobyes = new ArrayList<Bob>();
    

    所以现在你有一个泛型列表,其中包含 Bob 类型类的元素。 列表中每个元素的所有类型都是 Bob。

    如果你遍历它,你将拥有:

    foreach (Bob bob : bobyes)
       if (bob instanceof Bob)
          true; -- in this case always true;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多