2011-02-04 57 views
40

静态字段我刚开始就用一个例子,最能解释它:的Java:在抽象类

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

℃。 str = abc

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

所以我想输出是:

b.str = 123

c.str = ABC

是不是可行?

回答

3

把静态varibale在每个子类,并添加一个(而不是静态)抽象方法的抽象超:

abstract String getStr(); 

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

public class B extends A { 
private static String str; 

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

我编辑了我的帖子,是一个错误..接受。事情是,我需要每个对象都有一个对同一子类的所有对象共享的值的引用,但不一定在不同子类的对象之间共享。 – Tommy 2011-02-04 14:00:22

+0

我也更新了我的答案 – Ralph 2011-02-04 14:03:41

+0

当然。谢谢。 – Tommy 2011-02-04 14:11:00

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

但是这通常是一个坏主意。

+0

即使没有getter和setter,这也可以工作。然后确保str变量是公开的,这是不推荐的。 – 2011-02-04 14:04:37

2

只有静态变量的一个实例是存在于系统中。被加载的类前

静态变量将加载到系统中的开始。

因为这两个时间abc打印是因为你在最后设置str的值为abc。

2

这将打印您需要的输出:

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

如果你想要类B和C有不同的静态变量,你需要在这些类中声明的变量。基本上,静态成员和多态不会在一起。

注意,通过引用访问静态成员是在可读性方面有真的糟糕的主意 - 这使得它看起来这取决于参考的价值,当它不是真的。所以,当前的代码将无法编译,甚至当你移动str到B和C.相反,你需要

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

如果你真的需要多态访问值(即通过一个实例)然后一个选项是制作一个多态吸气剂:

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

既然你硬编码在子类中的价值或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()); 
    } 
} 
0

我想接近这个是使用一个单独的B类和C模仿静态方法和字段的一种方式。该既可扩展抽象类A,但将有str自己的价值观..

1

这是我做的,以避免必须实现在每个子类中的方法相同。它基于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"); 
    } 
}