简体   繁体   中英

Initializing a final variable in an abstract class (Java)

So I have this abstract class

 public abstract class A {

   protected final boolean b;

   protected A (boolean b){
    this.b = b;
   }

}

And this class that extends A

 public class C extends A{

   protected C() {
    super(false);
   }

}

I dont want "b" to be able to change its' value once it's initialized But I dont know how to do it without the compiler going haywire.

Any suggestions are welcome. Thanks in advance.

EDIT1: static removed from b.

EDIT 2: Ok realised the problem and fixed see above . Special thanks to J.Lucky :)

I'd suggest you make use of the final keyword.

Try the following codes:

abstract class A {

    final protected boolean b;

    A(boolean b) {
        this.b = b;
    }

    //No setter method
    //public abstract void setB(boolean b);
    public abstract boolean getB();
}

class C extends A {

    C(boolean b) {
        super(b);
    }

    @Override
    public boolean getB() {
        return b;
    }
}

Sample implementation would be:

public static void main(String args[]) {
    C c = new C(true);
    System.out.println(c.getB());
}

Since b now is a final variable, you will be forced to initialize it on your constructor and you will not have any way of changing b anymore. Even if you provide a setter method for b , the compiler will stop you.

EDIT 2:

Say you created another class called 'D' and this time you know you want to set it to false by default. You can have something like:

class D extends A {
    D() {
        super(false);
    }

    //You can also overload it so that you will have a choice
    D(boolean b) {
        super(b);
    }


    @Override
    public boolean getB() {
        return b;
    }

    public static void main(String[] args) {
        D defaultBVal = D();
        D customBVal = D(true);

        System.out.println(defaultBVal.getB()); //false
        System.out.println(customBVal.getB()); //true
    }
}

Solution: You should change the boolean into a Boolean, make it private, provide a getter and a protected setter. In the setter you should check whether the Boolean has been initialized. If so, you should either ignore resetting, or throw and Exception

well how about this:

public abstract class A {

   private static Boolean b;

   //setB is declared here and, depending on the class that implements it, 
   //it initializes the value of the variable "b"

   protected abstract void setB();

}

public class C extends A{

   protected void setB() {
     if(b != null) b = true;
   }
}

Now the variable is only initialized once when its called. There are still some problems. Someone could use reflection to change the value. Also, when the object is serialized is possible that someone could change the value. If you have a multiple threads accessing this then you should synchronize the method. However, if these aren't issues then this solution might work for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM