子类Java中的静态变量

子类Java中的静态变量,java,oop,object,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 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
       }
    }
可能吗?或者我需要在每个子类中声明静态变量吗?我尝试过,当我尝试访问静态变量时,每个类的静态变量值都是相同的。

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


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

您当前的代码不会执行您想要的操作,因为
陆军
类中只有一个
攻击
变量,并且它只能有一个值

您可以在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()
不是一个变量,也不是静态的,它仍然满足您的要求-每个子类都可以有一个由该子类的所有实例共享的不同值。

静态变量在类加载器首次加载类时初始化

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

new Warrior();
System.out.println(Warrior.attack);//output would be 50
我想说的是,您在Army类中创建了一个getAttack方法,并让Warrior和其他人覆盖它。 比如:

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

class Warrior extends Army{
  public int getAttack() {
      return 50;
  }
}
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;
}
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);
    }
}

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

public enum Attack {
    Army,
    Warrior,
    Archer; 
}


在一个完美的世界里,你会做如下事情:

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

class Warrior extends Army{
  public int getAttack() {
      return 50;
  }
}
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;
}
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);
    }
}
不幸的是,Java不允许这样做

你能得到的最接近的可能是:

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

class Warrior extends Army{
  public int getAttack() {
      return 50;
  }
}
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;
}
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);
    }
}

这是不可能做到这一点,你正试图这样做

您想要实现的是,在基类中有一个
静态
变量,然后为其每个子类提供相同变量的不同值

因为它是静态变量,所以所有对象的值都相同。一个子类不能有一个值,另一个子类不能有另一个值。因为它是两个类的一个常见静态变量。因此,它的值对于两个子类都是通用的


您可以在每个子类中使用静态变量,即,
Warrior
拥有自己的静态变量,
Archer
拥有自己的静态变量。

我假设您的直接问题(静态是否可以继承)已经得到了回答。 我想我应该建议另一种方法:

根据您的问题,我假设您希望避免向每个实例添加4个字节,每个实例具有唯一的attackvalue,因为每个战士有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;
    }
}
级陆军{
私有最终ArmyConfiguration配置;
公军(){
这(“军队”);
}
公共军队(字符串配置名称){
this.configuration=ConfigFactory.getInstance().getConfiguration(configurationName)
}
public ArmyConfiguration getArmyConfiguration(){return configuration;}
}
阶级战士{
超级战士;
}
弓箭手{
超级射手;
}
类配置工厂{
私有静态配置工厂实例;
公共同步ConfigFactory getInstance(){
if(实例==null){
实例=新的ConfigFactory();
}
返回实例;
}
私有地图;
公共工厂(){
this.configMap=new HashMap();
configMap.put(“陆军”,新的陆军配置(0));
configMap.put(“战士”,新的兵种配置(50));
configMap.put(“Archer”,新的ArmyConfiguration(75));
}
public ArmyConfiguration getConfiguration(字符串名称){
返回configMap.get(名称);
}
}
类别军备配置{
公共最终int攻击值;
公共ARMY配置(最终int攻击值){
this.attackValue=attackValue;
}
}
当然,这并不理想(单例可能不是您想要的)。此设置允许您从磁盘加载配置,而无需重新编译。(在ConfigFactory构造函数期间,从磁盘加载文件,解析它并构造实例)


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

“每个战士对象的攻击值为50”不正确,静态变量不属于对象静态变量与声明它的类的每个对象共享该值。所以每个子类也会有这个值。如果主类或其他子类更改了该值,则每个类(无论是父类还是子类)都将具有新值。因此,是的,您需要为每个子类声明一个新的静态变量。可能的重复项您需要为每个子类声明一个新的静态变量。为什么这是一个静态变量?对于常量,这将起作用(尽管需要使用int attackValue扩展枚举)。当他试图从外部文件加载这些值时,尽管这会崩溃。