Java:抽象类中的静态字段

发布于 2024-10-16 01:16:04 字数 696 浏览 4 评论 0原文

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

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

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

所以我希望输出为:

b.str = 123

c.str = abc

这可行吗?

I just start out with an example, that explains it best:

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);
    }
}

This will print out:

b.str = abc

c.str = abc

But I would like a solution where each subclass that instantiate the super class, has their own class variable, at the same time I want to be able to reference that class variable through the identifier, or a method call, defined in the abstract super class.

So I would like the output to be:

b.str = 123

c.str = abc

Is that doable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

娇纵 2024-10-23 01:16:04

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

请注意,从可读性角度来看,通过引用访问静态成员确实是一个坏主意 - 它使得它看起来像是依赖于引用的值,而实际上它并不依赖于引用的值。真的。因此,当您将 str 向下移动到 B 和 C 时,您当前的代码甚至无法编译。 相反,您需要

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 来说也是如此)。

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

If you want classes B and C to have separate static variables, you'll need to declare the variables in those classes. Basically, static members and polymorphism don't go together.

Note that accessing static members through references is a really bad idea in terms of readability - it makes it look like it depends on the value of the reference, when it doesn't really. So your current code won't even compile when you've moved str down to B and C. Instead, you'll need

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

If you really need to access the value polymorphically (i.e. through an instance of A) then one option is to make a polymorphic getter:

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

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

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

(and the same for C).

That way you get the behaviour you want in terms of not having a separate variable per instance, but you can still use it polymorphically. It's a little odd for an instance member to return a static value like this, but you're using the value for polymorphism of type, basically...

随梦而飞# 2024-10-23 01:16:04
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);
}

但这通常是一个坏主意。

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

Then you'll be able to have

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

The setter and getter are my addition, you can go by simply making the variable non-static.

Update If you want to have the static-per-subclass, then you can have:

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

and then:

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

But this is generally a bad idea.

转身以后 2024-10-23 01:16:04

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

abstract String getStr();

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

public class B extends A {
 private static String str;

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

Put the static varibale in each subclass and add a (not static) abstract method to the abstract superclass:

abstract String getStr();

Then implement the getStr() method in each subclass by returning the static field of this special subclass.

public class B extends A {
 private static String str;

  @Override
  public String getStr() {
    return B.str;
  }
}
街道布景 2024-10-23 01:16:04

系统中仅存在一个静态变量实例。

静态变量将在类加载之前加载到系统中。

两次打印 abc 的原因是因为您最后将 str 的值设置为 abc 。

only one instance of static variable is present in the system.

static variable will load into the system in the start before class is loaded.

reason both time abc is printed is because you set the value of str as abc in the last.

瑾夏年华 2024-10-23 01:16:04

这将打印您想要的输出:

public abstract class A{
}

public class B extends A{
    static String str;

    public B(){
        str = "123";
    }
}

public class C extends A{
    static String str;

    public C(){
        str = "abc";
    }
}

public class Main{

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

This will print the output you want:

public abstract class A{
}

public class B extends A{
    static String str;

    public B(){
        str = "123";
    }
}

public class C extends A{
    static String str;

    public C(){
        str = "abc";
    }
}

public class Main{

    public static void main(String[] args){
        A a = new B();
        A c = new C();
        System.out.println("B.str = " + B.str);
        System.out.println("C.str = " + C.str);
    }
}
ぶ宁プ宁ぶ 2024-10-23 01:16:04

由于无论如何您都在子类中对值或 str 进行了硬编码,因此您可以执行以下操作:

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

public class B extends A{
   public String getStr(){
      return "123";
   }
}

public class C extends A{
   public String getStr(){
      return "abc";
   }
}

这将在您的情况下实现这一点。

当然,那么你应该通过方法来调用它,如下所示:

public class Main{

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

Since you hardcode the value or str in subclasses anyway, you can do something like this:

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

public class B extends A{
   public String getStr(){
      return "123";
   }
}

public class C extends A{
   public String getStr(){
      return "abc";
   }
}

This would do the trick in your case.

Of course, then you should call it by method, like this:

public class Main{

    public static void main(String[] args){
        A b = new B();
        A c = new C();
        System.out.println("b.str = " + b.getStr());
        System.out.println("c.str = " + c.getStr());
    }
}
东北女汉子 2024-10-23 01:16:04

我这样做是为了避免必须在每个子类中实现相同的方法。这是基于Bozho的回答。也许它可以帮助某人。

import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author Uglylab
 */
public class SandBox {

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

}
 abstract class A{
    protected static Map<Class, String> values = new HashMap<>();


    public static String getStr(Class<? extends A> aClass) {
        return values.get(aClass);
    }

    public static void setStr(Class<? extends A> aClass, String s) {
        values.put(aClass, s);
    }

}

 class B extends A{
    public B(){
        setStr(this.getClass(),"123");
    }
}

 class C extends A{
    public C(){
        setStr(this.getClass(),"abc");
    }
}

It is what I did to avoid to have to implement the same method in every subclass. It is based on the answer of Bozho. Maybe it may help someone.

import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author Uglylab
 */
public class SandBox {

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

}
 abstract class A{
    protected static Map<Class, String> values = new HashMap<>();


    public static String getStr(Class<? extends A> aClass) {
        return values.get(aClass);
    }

    public static void setStr(Class<? extends A> aClass, String s) {
        values.put(aClass, s);
    }

}

 class B extends A{
    public B(){
        setStr(this.getClass(),"123");
    }
}

 class C extends A{
    public C(){
        setStr(this.getClass(),"abc");
    }
}
厌味 2024-10-23 01:16:04

我认为解决这个问题的一种方法是使用类 BC 的单例来模拟静态方法和字段。它们都可以扩展抽象类 A,但会有自己的 str 值。

I think one way to approach this is to use a singleton for class B and C to mimic static methods and fields. The can both extend abstract class A, but will have their own values of str..

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文