Java:抽象类中的静态字段

Tom*_*mmy 48 java static abstract

我刚开始用一个例子来解释它:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这将打印出来:

b.str = abc

c.str = abc

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

所以我希望输出为:

b.str = 123

c.str = abc

那可行吗?

Jon*_*eet 53

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

请注意,通过引用访问静态成员在可读性方面是一个非常糟糕的主意 - 它使它看起来像取决于引用的值,当它不是真的时.因此,当您str向下移动到B和C 时,您当前的代码甚至都不会编译.相反,您需要

System.out.println("b.str = " + B.str);
System.out.println("c.str = " + C.str);
Run Code Online (Sandbox Code Playgroud)

如果你真的需要以多态方式访问该值(即通过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;
    }
}
Run Code Online (Sandbox Code Playgroud)

(和C相同).

这样,您就可以获得所需的行为,而不是每个实例都有一个单独的变量,但您仍然可以多态地使用它.实例成员返回这样的静态值有点奇怪,但你使用的是类型的多态,基本上......

  • @biziclop:我也是.这就是我首先在Eclipse中请求它的原因:https://bugs.eclipse.org/bugs/show_bug.cgi?id = 21109 :) (9认同)
  • 我的经验是,甚至值得设置Eclipse将它们标记为编译错误. (5认同)

Boz*_*zho 6

public abstract class A {
    private String str;
    public String getStr() { return str;}
    protected void setStr(String str) { this.str = str; }
}
Run Code Online (Sandbox Code Playgroud)

然后你就能拥有

B b = new B();
b.getStr();
Run Code Online (Sandbox Code Playgroud)

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

更新如果您想拥有static-per-subclass,那么您可以拥有:

protected static Map<Class, String> values;
public abstract String getValue();
Run Code Online (Sandbox Code Playgroud)

然后:

public String getValue() {
    values.get(getClass());
}
public void setValue(String value) {
    values.set(getClass(), value);
}
Run Code Online (Sandbox Code Playgroud)

但这通常是一个坏主意.


Ral*_*lph 3

将静态变量放入每个子类中,并向抽象超类添加一个(非静态)抽象方法:

abstract String getStr();
Run Code Online (Sandbox Code Playgroud)

然后在每个子类中实现 getStr() 方法,返回这个特殊子类的静态字段。

public class B extends A {
 private static String str;

  @Override
  public String getStr() {
    return B.str;
  }
}
Run Code Online (Sandbox Code Playgroud)