Java:抽象类中的静态字段

2022-08-31 19:35:04

我只是从一个例子开始,这最好地解释了它:

public abstract class A{
    static String str;
}

public class B extends A{
    public B(){
        str = "123";
    }
}

public class C extends A{
    public C(){
        str = "abc";
    }
}

public class Main{

    public static void main(String[] args){
        A b = new B();
        A c = new C();
        System.out.println("b.str = " + b.str);
        System.out.println("c.str = " + c.str);
    }
}

这将打印出来:

b.str = abc

c.str = abc

但是我想要一个解决方案,其中实例化超类的每个子类都有自己的类变量,同时我希望能够通过抽象超类中定义的标识符或方法调用来引用该类变量。

所以我希望输出是:

b.str = 123

c.str = abc

这可行吗?


答案 1

如果希望类 B 和 C 具有单独的静态变量,则需要声明这些类中的变量。基本上,静态成员和多态性不会在一起。

请注意,就可读性而言,通过引用访问静态成员是一个非常糟糕的主意 - 它使它看起来取决于引用的值,而实际上并非如此。因此,当您向下移动到B和C时,您当前的代码甚至无法编译。相反,您需要str

System.out.println("b.str = " + B.str);
System.out.println("c.str = " + C.str);

如果您确实需要多态访问值(即通过A的实例),那么一种选择是创建一个多态getter:

public class A {
    public abstract String getStr();
}

public class B extends A {
    private static String str = "b";

    @Override public String getStr() {
        return str;
    }
}

(C也是如此)。

通过这种方式,您可以获得所需的行为,即每个实例没有单独的变量,但您仍然可以多态使用它。对于实例成员来说,返回这样的静态值有点奇怪,但是您正在使用该值进行类型的多态性,基本上...


答案 2
public abstract class A {
    private String str;
    public String getStr() { return str;}
    protected void setStr(String str) { this.str = str; }
}

然后,您将能够拥有

B b = new B();
b.getStr();

setter和getter是我的补充,你可以简单地使变量非静态。

更新如果你想拥有每个子类的静态,那么你可以拥有:

protected static Map<Class, String> values;
public abstract String getValue();

然后:

public String getValue() {
    values.get(getClass());
}
public void setValue(String value) {
    values.set(getClass(), value);
}

但这通常是一个坏主意。


推荐