【问题标题】:Java: Parent Methods accessing Subclasses' static variables?Java:访问子类的静态变量的父方法?
【发布时间】:2011-03-22 16:39:39
【问题描述】:

我正在尝试了解如何解决 Java 中的多态性。我创建了一个父类,它有太多的通用方法,所有子级都将以相同的方式使用。
每个子类的子类都共享静态信息,这些变量或信息将用于仅在父类中声明的方法中。
希望从 Parent 方法访问静态变量的问题似乎不太可能,
这是一种为每个实例声明公共信息的解决方案,但由于将有 1000 个实例,因此非常浪费内存。
我的意思的简单阐述是以下代码:

    class testParent {
    static int k;
    public void print()
    {
      System.out.println(k);    
    }
   }

   class testChild2 extends testParent 
   {

    static
    {
        testChild2.k =2;
    }
   }

   public class testChild1 extends testParent{
    static
    {
        testChild1.k = 1;
    }

    public static void main(String[] args)
    {

        new testChild1().print();
        new testChild2().print();

        new testChild1().print();
    }
 }

我期望的输出是
1
2
1.
但会发生什么:
1
2
2
有人可能会认为,在每个子类启动时,都会设置该子类的静态变量,然后引用该子类的所有方法都可以访问相应的“k”值。
但实际发生的是,所有子类都在同一个静态变量中进行编辑,该静态变量与所有子类共享,因此破坏了我为每个子类及其实例使用静态变量以及在父类中使用常用方法访问这些变量的全部观点。



知道怎么做吗?

【问题讨论】:

  • 是的,因为在我的应用程序中,每个子类在运行时都至少有 500 个实例,并且公共变量是字符串数组,你不认为不使用静态是巨大的内存浪费吗?

标签: java inheritance static polymorphism


【解决方案1】:

一种选择是通过抽象(非静态)方法访问子类的静态数据:

abstract public class Parent {
   protected abstract int getK();

   public void print() {
      System.out.println(getK());
   }
} 

public class Child1 extends Parent {
   private static final int CHILD1_K = 1;

   protected int getK() { return CHILD1_K; }
}

public class Child2 extends Parent {
   private static final int CHILD2_K = 2;

   protected int getK() { return CHILD2_K; }
}

【讨论】:

    【解决方案2】:

    当你新建 testChild2().print();执行了 testChield2 上的静态块并将值更改为 2。

    静态块仅在由 ClassLoader 加载时执行一次。

    这个给你想要的输出:

     class testParent {
        static int k;
        public void print()
        {
          System.out.println(k);    
        }
       }
    
       class testChild2 extends testParent 
       {
    
        {
            testChild2.k =2;
        }
       }
    
       public class testChild1 extends testParent{
        {
            testChild1.k = 1;
        }
    
        public static void main(String[] args)
        {
    
            new testChild1().print();
            new testChild2().print();
    
            new testChild1().print();
        }
     }
    

    每次实例化类时都会执行非静态代码块。

    【讨论】:

    • 当然,这有效,但您仍在更改单个静态变量的值。正确的解决方案是使用实例变量,而不是静态变量。
    • 是的。你需要隐藏变量,但它们也是邪恶的。如果您有这种情况,请尝试重新考虑设计。请查看有关阴影问题的此链接。 roseindia.net/java/java-tips/data/variables/…
    • 是的,在这个特定的例子中这将起作用,但是在我已经创建了类 A 的对象并且我创建了一个类 B 的新对象调用类 A 的实例中的方法的情况下,我们回到了这个。
    【解决方案3】:

    过早的优化是万恶之源。我认为您不会遇到数千个实例的任何内存问题,每个实例都有自己的数据,除非您正在使用某种小型嵌入式系统。静态变量并不打算做你想要用它们做的事情。

    【讨论】:

    • 我们不知道真正的数据是什么(整数?图像?),因此数千可能是 OP 的明显内存问题,也可能是过早的优化。
    • 老实说至少会有5个不同的子类,每个子类至少有200个实例,数据是字符串数组,我认为这会影响性能。
    【解决方案4】:

    静态变量特定于类本身。如果您希望类的不同实例中的相同字段具有不同的值,则该字段不能是静态的。

    解决方案:不要将k设为静态。

    class testParent {
        int k;
        public void print()
        {
            System.out.println(k);    
        }
    }
    
    class testChild2 extends testParent 
    {
        {
            this.k =2;
        }
    }
    
    class testChild1 extends testParent{
        {
            this.k = 1;
        }
    
        public static void main(String[] args){
            new testChild1().print();
            new testChild2().print();
            new testChild1().print();
        }
    }
    

    Demo
    (忽略 static class 业务 - 这只是为了让它在 ideone 中工作)。

    【讨论】:

    • 是的,但是在我的应用程序中,每个子类在运行时至少有 500 个实例,并且公共变量是字符串数组,你不认为不使用静态是巨大的内存浪费吗?
    • 我认为你没有抓住重点。除非每个实例的字符串数组与其他实例的字符串数组相同,否则静态不是答案。还有其他节省内存的技巧,例如string interning
    • 我不确定我是否不够清楚,但在每个子类中,所有实例都共享相同的字符串数组。
    • 一点都不清楚!您的问题询问在子类的每个实例中使用不同的值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-04
    • 2012-07-04
    • 1970-01-01
    • 2014-01-07
    • 2011-07-04
    • 2017-01-13
    • 2017-05-21
    相关资源
    最近更新 更多