我刚开始讲一个例子,最能解释一下:
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
可行吗?
答案 0 :(得分:48)
如果希望类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相同)。
通过这种方式,您可以获得所需的行为,而不是每个实例都有单独的变量,但您仍然可以多态地使用它。实例成员返回这样的静态值有点奇怪,但你使用的是类型的多态,基本上......
答案 1 :(得分: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是我的补充,你可以简单地使变量非静态。
更新如果您想拥有static-per-subclass,那么您可以拥有:
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);
}
但这通常是一个坏主意。
答案 2 :(得分:3)
将静态varibale放在每个子类中,并将一个(非静态)抽象方法添加到抽象超类中:
abstract String getStr();
然后通过返回此特殊子类的静态字段在每个子类中实现getStr()方法。
public class B extends A {
private static String str;
@Override
public String getStr() {
return B.str;
}
}
答案 3 :(得分:2)
系统中只存在一个静态变量实例。
静态变量将在加载类之前加载到系统中。
打印时间abc的原因是因为你将str的值设置为最后的abc。
答案 4 :(得分: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);
}
}
答案 5 :(得分: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());
}
}
答案 6 :(得分: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");
}
}
答案 7 :(得分:0)
我认为解决这个问题的一种方法是使用类B
和C
的单例来模仿静态方法和字段。这两者都可以扩展抽象类A
,但它们的值为str
..