【问题标题】:Generic Class name same as generic parameter泛型类名称与泛型参数相同
【发布时间】:2021-01-14 03:11:06
【问题描述】:

下面的代码

public class T<T> {
    public String toString() {
        return "Generic Types!";
    }
    public void run(T var) {
        Integer repeatCount = 12_57;
        System.out.println("debug: " + repeatCount + ", " + var.toString());
    }
    public static void main(String[] args) {
        System.out.println("Hello, World!");
        T<String> t = new T();
        t.run(t);
    }
}

public class T&lt;T&gt; 行给出警告 The type parameter T is hiding the type T&lt;T&gt; 。

T&lt;String&gt; t = new T() 行给出错误cannot make a static reference to non-static type T。

如果我将 public class T&lt;T&gt; 更改为 public class T&lt;K&gt; ,它适用于以下输出。但我不明白原因。 输出:

Hello, World!
debug: 1257, Generic Types!

我是泛型概念的新手,谁能解释一下上面的代码有什么问题?

【问题讨论】:

  • 你能解释一下你是否(如果是的话为什么)你想要使用这个令人困惑的命名?也许我们可以澄清一些潜在的混乱!通常,类名是描述性的,泛型参数是某事物的首字母,例如 T 代表类型,E 代表元素,K/V 代表键/值等。为什么要将类命名为 T ?
  • 这是我用来学习泛型 @Mark 的实验课,我明白命名约定是不正确的。

标签: java generics


【解决方案1】:

在这里你声明了一个类T,带有一个泛型参数T。在这个类中,T 现在可以引用两个东西:

  1. 泛型类
  2. 通用参数

这里用两个箭头表示:

public class T<T>
             ^ ^
             1 2

那么当你在这个类里面写T时,Java怎么知道你的意思是什么? 1和2都是类型!根据语言规则,意思 2 是受欢迎的。

如果您对它的规则感兴趣,它在 JLS 的 §6.4.1 中。

一个名为 n 的类型的声明 d 会隐藏任何其他名为 n 的类型的声明,这些类型在 d 出现在整个 d 的范围内的点上。

第二个T 在第一个T 的范围内,因此对其进行遮蔽。

您在类中对T 的所有引用都指向第二个T,即通用参数。为什么泛型参数T 是非静态的,请参阅Static method in a generic class? 或Generics - Why are Class type variables not valid in static contexts?

虽然,即使泛型参数T 是静态的,它也不是泛型的,您将无法像在T&lt;String&gt; 中那样对其进行参数化(实际上您不能将任何泛型参数设为泛型)。

除了重命名类名(首先是T),您还可以使用完全限定名来引用它:

yourpackagename.T

【讨论】:

    【解决方案2】:

    编辑:您正在创建一个类 T,其类型为 T 作为泛型参数。这两个T是不一样的,泛型参数T是隐藏类T在那个类中(即当你在类中使用T时,它会使用泛型参数T,而不是类T)。要解决此问题,请重命名泛型参数或类。

    你已经创建了一个类T,它的类型为T 作为一个泛型参数,它的类型T 作为一个泛型参数,它的类型为T...你可能可以看看为什么编译器会出现这个问题。 泛型参数的基本思想是使您的类可用于您在使用该类时可以传入的某些类型。一个例子是:

    public class MyObject<T> {
        private final T object;
        
        public MyObject(T object) {
            this.object = object;
        }
    
        public T getObject() {
            return this.object;
        }
    }
    

    你可以用作:

    MyObject<String> myStringObject = new MyObject<String>("Some string");
    String myStringObject2 = myStringObject.getObject();
    

    这里的好处主要是您可以在底部代码块中定义T 是什么,因此您不必只使MyObject 及其所有方法都与Object 一起使用并插入强制转换来使类型系统接受这一点(当您在该过程中出错时不会出现编译器错误)。

    【讨论】:

    • 为什么编译器会说“不能对非静态类型 T 进行静态引用”?错误消息似乎有误。
    • 哦,我知道我在这个异常的原因上是错误的。您使用与泛型类型名称相同的类名,导致泛型类型“隐藏”类名本身。因此,当您使用new T() 时,您实际上是在尝试创建泛型类型的新实例,而这是您无法做到的。您应该做的是重命名类或泛型类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多