If I have an abstract class that has variables of the form
protected static final int blah;
protected static final int blah2;
And i have two classes that extend this abstract class, and set these variables to "static final int" values from a constants file in their constructors, will they clobber eachother's values? If I want to do such a thing, what would you recommend I do?
So, for example, if i have
impl1 class:
public impl1 extends absClass{
public impl1(){
this.blah = CONSTANTS.impl1_blah;
this.blah2 = CONSTANTS.impl1_blah2;
}
}
impl2 class:
public impl2 extends absClass{
public impl2(){
this.blah = CONSTANTS.impl2_blah;
this.blah2 = CONSTANTS.impl2_blah2;
}
}
Is this allowed? If not, what should I do?
this.blah = CONSTANTS.impl2_blah;
this.blah2 = CONSTANTS.impl2_blah;
this allowed?
This isn't allowed, since your blah variables are declared as final. You must initialize them during class initialization, either in their declaration or in a static initializer block.
Furthermore, these variables are static, and so accessing them using this won't work: the variables belong to the class and not an instance.
If not, what should I do?
Use non-final variables in the superclass, or use specific constants in the subclasses.
if classes extending that abstract class are supposed to give their own values for those variables then you should consider a couple of protected abstract methods instead.
static variables can't be overridden. Those will be associated with the classes where you have defined them.
static final variables must be initialized when the class that declares them is initialized. This is before any instances of the class (or any subclass) are created. Your code won't compile without some sort of initialization for blah and blah2—either an initialization expression:
protected static final int blah = 42;
protected static final int blah2 = 1;
or in a static initializer block:
protected static final int blah;
protected static final int blah2;
static {
blah = 42;
blah2 = 1;
}
In either case, subclasses have no say in what blah and blah2 get assigned.
It seems from your example code that you want constants that can vary on a per-instance basis. It doesn't make sense for them to be static. You can do something like this:
public AbsClass {
protected final int blah;
protected final int blah2;
protected AbsClass(int blah, int blah2) {
this.blah = blah;
this.blah2 = blah2;
}
. . .
}
public class Impl1 extends AbsClass {
public Impl1() {
super(CONSTANTS.impl1_blah, CONSTANTS.impl1_blah2);
}
}
public class Impl2 extends AbsClass {
public Impl1() {
super(CONSTANTS.impl2_blah, CONSTANTS.impl2_blah2);
}
}
Polymorphism in Java don't work with attributes. Use some protected abstract getMethods() instead.
First of all this is final+static which means nothing to do with OOP, If you make them not static then It makes sense to talk about OOP on it. If you do not do them as private and access them using getters/setters then you are breaking encapsulation.
And you are making it final, means it can be initialized only once. You will get exception when you try to change the value of final attr.
Related
Consider an interface and its implementation,
interface A {
int a;
default void add() {
a = a+10;
}
public void sub();
}
class X implements A {
public sub() {
a = a-5;
}
}
I have to use the variable a in sub() function of class X. How can I do?
All variables declared inside interface are implicitly public static final variables(constants).
From the Java interface design FAQ by Philip Shaw:
Interface variables are static because Java interfaces cannot be instantiated in their own right; the value of the variable must be assigned in a static context in which no instance exists. The final modifier ensures the value assigned to the interface variable is a true constant that cannot be re-assigned by program code.
Since interface doesn't have a direct object, the only way to access them is by using a class/interface and hence that is why if interface variable exists, it should be static otherwise it wont be accessible at all to outside world. Now since it is static, it can hold only one value and any classes that implements it can change it and hence it will be all mess.
Hence if at all there is an interface variable, it will be implicitly static, final and obviously public!!!
The field a in the interface A always final and static and it isn't supposed to be modified in any way including reassigning it in an instance method.
Interfaces don't have the state. Abstract classes may.
abstract class A {
protected int a;
public void add() {
a += 10;
}
public abstract void sub();
}
final class X extends A {
public void sub() {
a -= 5;
}
}
I would use an abstract class instead of an interface. That way the variable can be modified by the extending class.
abstract class A{
int a=10;
void add(){
a=a+10;
}
public abstract void sub();
}
class X extends A{
public void sub(){
a=a-5;
}
}
Yes, We can use abstract class.
Since in interface variables declared are by default final.
Code with Interface
Code with Abstract Class
For example a class:
//class1
class A {
private A() { } // why would I make it private?
public A(int) { } //why isn't it implicitly public?
}
//class2
class B {
public static void main(String[] args) {
//A a = new A();
}
}
A constructor instantiates a class so why it has the access modifier?
Is there a case when we have to declare a constructor private?
A constructor instantiates a class so why it has the access modifier?
The modifier can be used so you control where the object can be constructed.
Is there a case when we have to declare a constructor private?
Say you have a factory method like
class A {
private A(int n) { }
public static A create(int n) {
return new A(n);
}
}
or you have a shared constructor which should be called directly.
class B {
public B(int n) {
this(n, "");
}
public B(String str) {
this(0, str);
}
private B(int n, String str) { }
}
or you have a Singleton
final class Singleton {
Singleton INSTANCE = new Singleton();
private Singleton() { }
}
however I prefer to use an enum which has a private constructor.
enum Singleton {
INSTANCE;
}
or you have a Utility class
final class Utils {
private Utils() { /* don't create one */ }
public static int method(int n) { }
}
however I prefer to use an enum in this case
enum Utils {
/* no instances */;
public static int method(int n) { }
}
Note: if you use a private constructor on a final class you can still create instances using nested classes, or reflection. If you use an enum you can't create an instance as easily/accidentally.
Warning: You can create instances of an enum using Unsafe
Note in enum the constructor has to be private
class BuySell {
BUY(+1), SELL(-1);
private BuySell(int dir) { }
}
You don't have to make it private explicitly as this is the default.
The private modifier when applied to a constructor works in much the same way as when applied to a normal method or even an instance variable. Defining a constructor with the private modifier says that only the native class (as in the class in which the private constructor is defined) is allowed to create an instance of the class, and no other caller is permitted to do so. There are two possible reasons why one would want to use a private constructor – the first is that you don’t want any objects of your class to be created at all, and the second is that you only want objects to be created internally – as in only created in your class.
Uses of private construtor:-
1) Private constructors can be used in the singleton design pattern
2) Private constructors can prevent creation of objects
This might also help Can a constructor in Java be private? the use cases of private constructor
Constructor are not responsible for Creating a object of a Class, these constructor are only responsible for initialize the member variables only.
There are various Reason behind this. One of the most popular reason behind this is design-Pattern.
//class1
class A {
private A() { } // why would I make it private?
}
why make private Constructor ?
If you want to make a Class singleton then your constructor must be private. then only it is possible to make a Class a Singleton.
I have a base class where I have a static variable defined. From this post I know every class extending the base class will have the same copy of the class variable (static variable). Is there a way to make each extending class have it own "copy of the class variable"? I tried declaring the base class abstract but no luck.
public abstract class BaseBlah{
private static int number_of_threads;
}
public class Blah1 extends BaseBlah{
}
public class Blah2 extends BaseBlah{
}
My case is a little more complicated than the example since I want each extended class to abstract one common type of tasks executed in its dedicated thread pool which is the class variable in this case.
Every class will have it's own copy if you give it a copy of the field, but not automagically.
public abstract class BaseBlah{
private static int number_of_threads;
}
public class Blah1 extends BaseBlah{
private static int number_of_threads;
}
public class Blah2 extends BaseBlah{
private static int number_of_threads;
}
All the classes have their own copy of number_of_threads
Note: this would be called hiding if the fields were not private rather than inheritance.
`
Here's a semi-hacky way to do it, using a HashMap in the base class:
public abstract class BaseBlah{
private static HashMap<Class<? extends BaseBlah>, Integer> numThreadsMap = new HashMap<>();
protected int getNumThreads() {
Integer i = numThreadsMap.get(getClass());
return i != null ? i : 0;
}
protected void setNumThreads(int n) {
numThreadsMap.put(getClass(), n);
}
}
The upside of this is that there's nothing to remember for future implementing classes of BaseBlah. Whenever you create a new extending class it will "automatically" create a new "static" variable for the class.
The downside is that in order to use this approach you have to access it from a non static context (i.e. with an instance). It will behave as a static variable, but you can't treat it as such. static and class extension don't like each other (as this example proves) so fully integrating the two is always messy.
I know that in Java an enum constant is implicitly static final variable. But the enum class can have an instance variable say size. So each enum constant will have a copy of 'size'.
What is the equivalent Java code for this? I mean it "seems" the static enum constant is using a non-static instance variable which is not possible normally?
enum Members{
A(1),B(2),C(3); // I have 3 enum constants here
private int size;
Members (int size) {
//System.out.println("Initializing var with size = "+size);
}
}
Equivalent code I know so far:
public final class Member extends Enums<Members> {
public static final Members A;
// ...
// What happened to size? How do A,B,C get a copy of size?
}
Edit : To restate my question-
I am interested in behind the scene implementation by compiler. I already know how to use enums. I am looking for what the compiler does? (so for example, if I simply write A, the compiler translates it to "public static final Member A". I want to know how compiler gives a copy of size to each A,B,C.
I mean it "seems" the static enum constant is using a non-static instance variable which is not possible normally?
It is absolutely possible: each static variable in the enum is an object in its own right, complete with its instance variables. The instance is static in the enum, but it does not make the context of the instance itself a static context.
public final class Member extends java.lang.Enums<Members> {
public static final Members A = new Member(1) {
public String toString() { return "A:"+size; }
};
public static final Members B = new Member(2) {
public String toString() { return "B:"+size; }
};
public static final Members C = new Member(3) {
public String toString() { return "C:"+size; }
};
private final int size;
protected Member(int size) { this.size = size; }
}
I mean it "seems" the static enum constant is using a non-static instance variable which is not possible normally?
What I meant by "normally" was that in non-enum classes a static variable can't access non static variables
It's still true: a static variable can't access non-static variables.
In your example code, you don't do this:
there is no static variable accessing non-static variables.
The constructor Members(int size) is not in a static context (a constructor never is).
A, B and C are all instances of the enum type Members,
and when these instances are created,
the constructor is called with the size parameter.
Once constructed, these objects will be treated as static constant values.
Perhaps another example can help:
class Person {
private final String name;
Person(String name) {
this.name = name;
}
}
class EmployeeDatabase {
private static final Person CEO = new Person("Jack");
}
Here EmployeeDatabase.CEO is a static constant object with a non-static field name.
This is just like Members.A, a static constant object with a non-static field size.
I want to know how compiler gives a copy of size to each A,B,C.
Exactly the same way as it passes constructor parameters to any object.
You can read all about enums in the docs.
Please see the below code --
public interface TestInterface {
public static String NON_CONST_B = "" ;
}
public class Implemented implements TestInterface {
public static String NON_CONST_C = "" ;
}
public class AutoFinal {
public static String NON_CONST_A = "" ;
public static void main(String args[]) {
TestInterface.NON_CONST_B = "hello-b" ;
Implemented.NON_CONST_C = "hello-c";
AutoFinal.NON_CONST_A = "hello-a" ;
Implemented obj = new Implemented();
}
}
However, the compiler complains that TestInterface.NON_CONST_B is final --
AutoFinal.java:6: error: cannot assign a value to final variable NON_CONST_B
TestInterface.NON_CONST_B = "hello-b" ;
^
1 error
why ?
Regarding:
public interface TestInterface {
public static String NON_CONST_B = "" ;
}
public class AutoFinal {
public static void main(String args[]) {
TestInterface.NON_CONST_B = "hello-b" ;
// ....
}
}
However, the compiler complains that TestInterface.NON_CONST_B is final --
But it in fact is final whether you explicitly declare it to be or not since it is declared in an interface. You can't have non-final variables (non-constants) in an interface. It's also public and static whether or not it has been explicitly declared as such.
Per the JLS 9.3 Interface Field (Constant) Declarations:
Every field declaration in the body of an interface is implicitly public, static, and final. It is permitted to redundantly specify any or all of these modifiers for such fields.
In java, all variables was declared in Interfacel are public static final default
Variables declared in interface are always public static final by default in java. Interface variables are static because Java interfaces cannot be instantiated in their own right; the value of the variable must be assigned in a static context in which no instance exists. The final modifier ensures the value assigned to the interface variable is a true constant that cannot be re-assigned by program code.
As all answers saying that by default all the variables declared in Interface are static final variables.
FYI, you can not declare a static method in interface. You can find the reason in this SO question.
however, you can declare Inner Class in an interface that can contain static methods and non static and non final variables.