20

假设我有以下课程:

class Parent
{
    private int ID;
    private static int curID = 0;

    Parent()
    {
         ID = curID;
         curID++;
    }
}

这两个子类:

class Sub1 extends Parent
{
    //...
}

class Sub2 extends Parent
{
    //...
}

我的问题是这两个子类从父类共享相同的静态 curID 成员,而不是具有不同的成员。

所以如果我这样做:

{
    Sub1 r1 = new Sub1(), r2 = new Sub1(), r3 = new Sub1();
    Sub2 t1 = new Sub2(), t2 = new Sub2(), t3 = new Sub2();
}

r1,r2,r3 的 ID 为 0,1,2,t1,t2,t3 的 ID 为 3,4,5。而不是这些,我希望 t1,t2,t3 具有值 0,1,2,即使用 curID 静态变量的另一个副本。

这可能吗?如何?

4

9 回答 9

14

虽然static字段/方法是继承的,但它们不能被覆盖,因为它们属于声明它们的类,而不是对象引用。如果您尝试覆盖其中之一,您将要做的就是隐藏它。

于 2013-06-18T14:53:39.887 回答
13

正如其他人已经写的那样,静态成员绑定到类,因此您需要在类级别跟踪 id,例如:

abstract class Parent {
    private int ID;

    Parent() {
         ID = nextId();
    }

    abstract protected int nextId();
}

class Sub1 extends Parent {
    private static int curID = 0;

    protected int nextId() {
       return curID++;
    }

    //...
}

class Sub2 extends Parent {
    private static int curID = 0;

    protected int nextId() {
       return curID++;
    }

    //...
}

请注意,这种方法不是线程安全的 - 但问题中的代码也不是。您不能从不同的线程同时从同一个子类创建新对象。

于 2013-06-18T14:56:26.067 回答
2

这是可能的,但不使用单个计数器。每个子类型都需要一个计数器。例如,如下所示:

private static Map<Class<?>, Integer> counters = new HashMap<>();

Parent() {
     Integer curID = counters.get(this.getClass());
     if (curID == null) {
         curID = 0;
     }
     ID = curID;
     curID++;
     counters.put(this.getClass(), curID);
}

注意:以上不是线程安全的。但是您的初始代码也不是...

于 2013-06-18T14:59:16.183 回答
1

静是静是静。只有一个 curID 实例,句点。因此,如果您想要 Sub1 和 Sub2 的单独计数器,您可以在每个类中声明静态。

于 2013-06-18T14:53:37.563 回答
1

与其他答案所说的不同,您的问题有一个解决方案,尽管它不涉及“静态继承”。你应该有一个每类 ID 生成器。

这是一个很好的例子:

Java:访问子类的静态变量的父方法?

于 2013-06-18T14:59:07.923 回答
0

静态元素根本不被继承。

实际上没有任何这样的东西Sub1.curID- 这是一种合法(但令人困惑)的引用方式Persion.curID

不幸的是,没有任何方法可以使用静态引用来做你所追求的。它们从根本上不能也不能使用固有特性——因为它们是静态解析的,它们不能依赖动态调度,因此不能依赖运行时多态性。鉴于 JVM/编译器以这种方式处理静态变量,我相信没有任何解决方法可以让你做你想做的事。

如果 ID 确实需要是静态的,那么您需要在每个子类中定义不同的静态变量。

于 2013-06-18T14:54:51.503 回答
0

static成员是JVM中Parent.class对象的PermGen一部分。该类的所有实例共享相同的静态变量。

每个子类都应该有自己的static curID.

于 2013-06-18T14:55:00.870 回答
-1

静态字段不会被继承。每个实例都将使用相同的字段。为了完成你想要的,我会将该字段更改为一个实例字段,并且要么有一个内部递增该字段的实例,要么如果你需要创建三个实例,你可以有一个构造函数来传递递增的值。

于 2013-06-18T14:54:40.960 回答
-1

您正在使用static变量

  • 不同的对象没有static变量的副本,
  • 只有static变量的副本,它将为所有实例共享

关于静态变量继承,它们根本不被继承

所以即使你说

r1.curID;
t1.curID;

这将意味着同样的事情,即Parent.curID

当您static从类的实例更改变量时,如果另一个实例正在访问该变量,它将获得更改后的值作为其共享变量

于 2013-06-18T14:55:56.810 回答