子类Java中的静态变量

时间:2014-12-08 09:32:58

标签: java oop object

我需要一个与对象无关的静态变量,而是与类本身有关。但是,该变量也必须与父类或扩展相同父类的所有其他子类无关。

让我们说:

    class Army{
      static int attack = 0;
    }

    class Warrior extends Army{
      public Warrior(){ 
        attack = 50;   // every Warrior object will have attack value of 50
      }
    }

    class Archer extends Army{
       public Archer(){ 
         attack = 75; // every Archer object will have attack value of 75
       }
    }

有可能吗?或者我是否需要在每个子类中声明静态变量?我试过,当我试图访问静态变量时,静态变量的值对于每个类都是相同的。

7 个答案:

答案 0 :(得分:5)

您当前的代码将无法执行您想要的操作,因为attack类中只有一个Army变量,并且它只能有一个值。

您可以在Army中使用返回默认值的方法:

public int getAttack()
{
    return 10;
}

然后你可以在子类中覆盖这个方法:

class Warrior extends Army
{
    ...
    @Override
    public int getAttack()
    {
        return 50;
    }
    ...
}

class Archer extends Army
{
    ...
    @Override
    public int getAttack()
    {
        return 75;
    }
    ...
}

即使getAttack()不是变量,并且它不是静态的,它仍然满足您的要求 - 每个子类可以具有该子类的所有实例共享的不同值。

答案 1 :(得分:2)

不,不可能。 父类对其子类中的静态或非静态成员一无所知。

但是,您发布的代码告诉我要覆盖静态变量。这也是不可能的,只能覆盖非静态方法(如果它们具有适当的访问级别)。

答案 2 :(得分:1)

攻击属性不能是静态的,您必须在每个类中定义它 但请考虑使用枚举。

public enum Attack {
    Army,
    Warrior,
    Archer; 
}

public class Army {
    private final Attack attack = Attack.Army;
}

public class Warrior extends Army{
    private final Attack attack = Attack.Warrior;
}

public class Archer extends Army{
    private final Attack attack = Attack.Archer;
}

答案 3 :(得分:0)

当类首次由类加载器加载时,静态变量被初始化。

当您尝试创建说Warrior的实例时,您正在重置攻击变量。因此,在使用Warrior.attack之前,请执行以下操作:

new Warrior();
System.out.println(Warrior.attack);//output would be 50

我会说你在陆军类中创建一个getAttack方法,然后让Warrior和其他方法覆盖它。 类似的东西:

class Army{
  public int getAttack() {
      return 0;
  }
}

class Warrior extends Army{
  public int getAttack() {
      return 50;
  }
}

答案 4 :(得分:0)

在一个完美的世界中,你会做类似的事情:

abstract class Army {
    // Final to make sure it is filled in - abstract to postpoone that to sub-classes.
    // NB: NOT valid Java.
    abstract final int attack;
}

不幸的是,Java不允许这样做。

你能得到的最接近的东西是:

class Army {

    // Final to make sure it is filled in.
    final int attack;

    // Forces subclassses to use super(attack).
    public Army(int attack) {
        this.attack = attack;
    }
}

class Warrior extends Army {

    public Warrior() {
        // I get an error if I don't do this.
        super(50);
    }
}

答案 5 :(得分:0)

不可能按照你想要的方式这样做。

你想要实现的是,在基类中有一个static变量,然后为每个子类赋予相同变量的不同值。

因为它是静态变量,所以它对所有对象都具有相同的值。它不能为一个子类提供一个值,为其他子类提供其他值。因为它是两个类的一个常见静态变量。因此,无论它的价值如何,对于两个子类都是常见的。

你可以做的是在每个子类中都有静态变量,即Warrior有自己的静态变量,Archer有自己的静态变量。

答案 6 :(得分:0)

我假设你的直接问题(可以静态继承)已被回答。 我以为我建议采用另一种方法:

从你的问题我假设你想避免为每个实例添加4个字节及其独特的攻击值,因为每个战士有50次攻击,它应该是列出这个的1个地方。 对于1个数字,此解决方案仍将花费4个字节,但如果超过1个这样的数字,则会更优化。

class Army {
    private final ArmyConfiguration configuration;
    public Army() {
        this("Army");
    }
    public Army(String configurationName) {
        this.configuration = ConfigFactory.getInstance().getConfiguration(configurationName)
    }

    public ArmyConfiguration getArmyConfiguration() { return configuration; }
}

class Warrior {
    super("Warrior");
}

class Archer {
    super("Archer");
}

class ConfigFactory {
    private static ConfigFactory instance;

    public synchronized ConfigFactory getInstance() {
        if (instance == null) {
            instance = new ConfigFactory();
        }
        return instance;
    }

    private Map<Class, ArmyConfiguration> configMap;

    public ConfigFactory() {
        this.configMap = new HashMap<Class, ArmyConfiguration>();
        configMap.put("Army", new ArmyConfiguration(0));
        configMap.put("Warrior", new ArmyConfiguration(50));
        configMap.put("Archer", new ArmyConfiguration(75));
    }

    public ArmyConfiguration getConfiguration(String name) {
        return configMap.get(name);
    }
}

class ArmyConfiguration {
    public final int attackValue;

    public ArmyConfiguration(final int attackValue) {
        this.attackValue = attackValue;
    }
}

当然,这并不理想(单身可能不是你想要的)。此设置将允许您从磁盘加载配置,而无需重新编译。 (在ConfigFactory构造函数中,从磁盘加载文件,解析它并构造实例)

这样,您可以将对象的实际设置/配置与这些对象所需的逻辑分开。对于小规模的东西,硬编码是一种选择,对于您可能想要提取的大型项目。