Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: static field in abstract class

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?

like image 936
Tommy Avatar asked Feb 04 '11 13:02

Tommy


People also ask

Can an abstract class have a static field?

Can an abstract class have static methods? Yes, abstract class can have Static Methods. The reason for this is Static methods do not work on the instance of the class, they are directly associated with the class itself.

Can abstract class have static variables in Java?

Type of variables: Abstract class can have final, non-final, static and non-static variables.

Can we declare static variable in abstract method?

Yes, of course you can define the static method in abstract class.

What is the use of static method in abstract class?

If a method is declared as static, it is a member of a class rather than belonging to the object of the class. It can be called without creating an object of the class. A static method also has the power to access static data members of the class.


2 Answers

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...

like image 100
Jon Skeet Avatar answered Sep 23 '22 17:09

Jon Skeet


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.

like image 32
Bozho Avatar answered Sep 22 '22 17:09

Bozho