In Java, why can't I declare a final member (w

2019-01-12 09:00发布

In a Java program, I have multiple subclasses inheriting from a parent (which is abstract). I wanted to express that every child should have a member that is set once only (which I was planning to do from the constructor). My plan was to code s.th. like this:

public abstract class Parent {
    protected final String birthmark;
}

public class Child extends Parent {
    public Child(String s) {
        this.birthmark = s;
    }
}

However, this seems to not please the Java gods. In the parent class, I get the message that birthmark "might not have been initialized", in the child class I get "The final field birthmark cannot be accessed".

So what's the Java way for this? What am I missing?

标签: java final
8条回答
迷人小祖宗
2楼-- · 2019-01-12 09:18

Declare a constructor in the superclass that's called by the subclass. You must set the field in the superclass to make sure it's initialized, or the compiler can't be sure the field is initialized.

查看更多
一夜七次
3楼-- · 2019-01-12 09:19

Another Java-ish way to do this is probably to have the parent class to define an abstract "getter", and have the children implement it. It's not a great way to do it in this case, but it in some cases it can be exactly what you want.

查看更多
可以哭但决不认输i
4楼-- · 2019-01-12 09:33

Why not delegate initialization to a method. Then override the method in the parent class.

public class Parent {
   public final Object x = getValueOfX();
   public Object getValueOfX() {
      return y;
   }
}
public class Child {
  @Override
  public Object getValueOfX() {
     // whatever ...
  }
}

This should allow custom initialization.

查看更多
Ridiculous、
5楼-- · 2019-01-12 09:36

You can't do it because while comparing the parent class, the compiler can't be sure that the subclass will initialize it. You'll have to initialize it in the parent's constructor, and have the child call the parent's constructor:

public abstract class Parent {
    protected final String birthmark;
    protected Parent(String s) {
        birthmark = s;
    }
}

public class Child extends Parent {
    public Child(String s) {
        super(s);
        ...
    }
}
查看更多
姐就是有狂的资本
6楼-- · 2019-01-12 09:39

Yes, the final members are to be assigned in the class in which they are declared. You need to add a constructor with a String argument to Parent.

查看更多
何必那么认真
7楼-- · 2019-01-12 09:40

Pass it to the parent constructor:

public abstract class Parent {
    private final String birthmark;
    public Parent(String s) {
        birthmark = s;
    }
}

public class Child extends Parent {
    public Child(String s) {
        super(s);
    }
}
查看更多
登录 后发表回答