通用类是否共享静态成员?

6
我希望询问关于通用类的问题。当我从一个通用类创建两个对象实例时会发生什么?它们共享每个静态成员,还是都有自己的静态成员?
例如:
public A<?>(){
    public static Integer member = 0;
}

A<Integer> integer = new A<Integer>();
A<String> string = new A<String>();

IntegerStringmember背后是否具有相同的引用?


2
你的问题是有效的,但你发布的代码有误:它既不是有效的构造函数,也不是类声明。你问题的答案是:是的,它们共享每个静态成员。此外,你可以自己回答这个问题:System.out.println(integer.member == string.member); 这与 System.out.println(A.member == A.member); 相同(因为它们都是 static)。 - jlordo
如果成员本身是泛型的呢?例如 public class MyClass<T> { public static T member; } 会发生什么? - Ravi K Thapliyal
@RaviThapliyal:无法编译。 - jlordo
这就是当你太懒了,不想尝试代码会发生的事情... - Luiggi Mendoza
@Lucia - 最好不要在问题中“修复”代码(即使它显然是错误的),因为这可能会掩盖最初引起该人来到这里的问题。如果你发现了一个错误,请留下评论或发布答案。 - Leigh
显示剩余2条评论
6个回答

11
public class A<T>{
    public static Integer member = 0;

    public static void main(String[] args)
    {
      A<Integer> integer = new A<Integer>();
      A<String> string = new A<String>();

      integer.member++;
      System.out.println(string.member);
    }
}

输出

1

是的,这两个实例共享同一个member变量。


2
+1 这是一个很好的例子。值得注意的是,integer.member++; 是不好的编程风格,代码检查器也不鼓励这样的代码。static 成员应该总是以静态方式访问,即:A.member++; - jlordo
当你有疑问时,测试它! :) +1 - Pragmateek

3
好问题,但答案是:不能,因为一旦编译完成,就不存在A<Integer>或A<String>之类的东西,只有A,这是由于Java使用了泛型类型擦除来保持向后兼容性

在其它语言中,如C#,事情会按照你的期望进行,因为C#从一开始就采用了泛型。


感谢提到C#。我的想法来源于一个C#的例子。 - Quirin
我处于类似的情况:使用Java很难回到10年前,但我相信它会填补这个空白。 :) - Pragmateek

2

没有类字面量(A<Integer>.classClass实例)表示任何参数化类型(如A<Integer>)。始终只有一个原始版本A(即A.class),所有静态成员都属于该版本。

这就是为什么您不会像A<Integer>.member那样做,它应该始终是原始版本A.member(这是所有实例共享的唯一版本)。

您可以在此处阅读有关此主题的文章 - 通用类型的每个实例是否有一个静态字段实例?.


0

是的,它们会共享变量。关于静态类变量的规则不会因为使用泛型而改变。静态类变量被所有实例共享。


1
这不应该被视为理所当然。在C++中,A<Integer>A<String>将是具有不同静态数据成员的不同类。 - Nicola Musatti
@NicolaMusatti:这是一个带有java标签的问题... - jlordo
确实。然而,Java泛型受到C++模板的启发,我认为指出它们之间的区别很重要。 - Nicola Musatti
@NicolaMusatti,那么为什么您自己的答案中没有这个呢? :) - Ravi K Thapliyal
因为Simon似乎认为只有一个A类,我想指出这对于OP来说可能并不是显而易见的。 - Nicola Musatti
直到我读了Simon的回答后才想到这点。 - Nicola Musatti

0

它们都共享静态属性,因为在运行时,A<Integer>A<String>不是不同的类。


0
你只需要认为泛型是用于编译目的。在运行时,A<Integer>A<String>之间没有区别:它们都是A的实例。因此,静态成员对你创建的任何实例都是共同的,而不考虑你使用的类型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接