Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abstract class with final uninitialized field

Tags:

java

oop

I was wondering if the below code makes any sense, since the compiler warns that "the blank final field objects may not have been initialized". Is there a better way of doing this?

public abstract Test {   protected final ArrayList<Object> objects; }  public TestSubA extends Test {    public TestSubA() {     objects = new ArrayList<Objects>(20);     // Other stuff   } }  public TestSubB extends Test {    public TestSubB() {     objects = new ArrayList<Objects>(100);     // Other stuff   } } 
like image 203
Cantillon Avatar asked Feb 24 '10 16:02

Cantillon


People also ask

Can abstract class have final variable?

An abstract class may contain non-final variables. Type of variables: Abstract class can have final, non-final, static and non-static variables. The interface has only static and final variables.

Can we declare final method in abstract class?

Declaring abstract method final Similarly, you cannot override final methods in Java. But, in-case of abstract, you must override an abstract method to use it. Therefore, you cannot use abstract and final together before a method.

Can we initialize variable in abstract class?

Constructors: b. Since an abstract class can have instance variables. Therefore, we can define constructors within the abstract class to initialize instance variables.

Can we declare Datamember as abstract?

Abstract classes in Java are classes which cannot be instantiated, meaning we cannot create new instances of an abstract class. The purpose of an abstract class is to function as a base for subclasses. but why java allows to define data member in an abstract class, where we can not create object of an abstract class.


2 Answers

I would make the field final and force the constructors to pass the value up:

public abstract class Test {   private final ArrayList<Object> objects;    protected ArrayList<Object> getObjects() {     return objects;   }    protected Test(ArrayList<Object> objects) {     this.objects = objects;   } }  public class TestSubA extends Test {    public TestSubA() {     super(new ArrayList<Object>(20));     // Other stuff   } }  public class TestSubB extends Test {    public TestSubB() {     super(new ArrayList<Object>(100));     // Other stuff   } } 
like image 115
Jon Skeet Avatar answered Oct 10 '22 15:10

Jon Skeet


The problem with initializing the final parameters directly in the constructor of the sub-classes is that you need to do it all in one line since super() must be the first statement of the constructor. So instead, I prefer to make the constructor non-public and make a static build method like this:

public abstract class Test {   protected final ArrayList<Object> objects;    protected Test(ArrayList<Object> objects) {     this.objects = objects;   } }  public class TestSubA extends Test {   public static TestSubA build() {     ArrayList<Object> objects = new ArrayList<Object>(20);     objects.put(...);     // Other stuff     return new TestSubA(objects);   }    private TestSubA(ArrayList<Object> objects) {     super(objects);   } } 
like image 25
qwertzguy Avatar answered Oct 10 '22 17:10

qwertzguy