Home > Software design >  Initialize a Java Collection in Class that was declared in Interface
Initialize a Java Collection in Class that was declared in Interface

Time:03-06

Declared a Vector in the Interface and set it to null, want to initialize it later in the class that implemented the Interface, java is giving error with the following code, how can i initialize it any other way?

import java.util.Vector;

interface machine {
    Vector<Integer> temp = null;
    public int compute();
}

class App implements machine {
    App(Vector<Integer> x) {
        //error here, can't assign value to temp as it is declared in interface, any other way of initializing??
        temp = x;
    }

    @Override
    public int compute() {
        int sum = 0;
        for (int x : temp) {
            sum  = x;
        }
        return sum;
    }
}

public class Finals {
    public static void main(String[] args) {
        Vector<Integer> x = new Vector<>();
        for (int i = 0; i < 10; i  ) {
            x.add(i);
        }
        App a = new App(x);
        System.out.println(a.compute()); 
    }
}

CodePudding user response:

Java, the language, is designed with the following ideas in mind:

  • Fields are never really considered as part of a type's "public API". Yes, a public field can be written and can be modified from the outside, but almost no java code out there does this, and many language features simply do not support it. For example, method references exists (someExpr::someMethodName is legal java), but the there is no such thing as a field reference.

  • Interfaces exist solely to convey API - to convey what a type is supposed to be able to do, it is not a thing that was intended for conveying how it is to do it. In other words, interface (hence the name) yes, implementation no.

Add these 2 concepts together and you see why what you want (put a field in an interface) is not supported. A field is not part of an interface (rule #1), therefore it must be implementation, and interfaces can not carry implementation details (rule #2), hence: You cannot put a field in an interface.

As a consequence, the java lang spec dictates that any field declaration in an interface is inherently public static final - it's a constant. You can't make it not-public-static-final - putting private on it as modifier is a compiler error. There is no modifier that means 'unstatic'.

You have 2 options:

  • You intended that field solely as implementation: You decided that all classes that implement this interface will need this field, so, might as well declare it in the interface and save the typing, right? Well, what you're doing there is grouping common aspects of the implementation together. Java supports this, but only in abstract classes. This happens all the time in java: There is java.util.List (an interface), and java.util.AbstractList (an abstract class that implements that interface, that provides a bunch of common behaviour), and java.util.ArrayList (the most commonly used implementation. It extends AbstractList).

  • You actually need the 'interface' part of that field: You want to write some code, either in the interface file itself (via default methods), or in code that receives an object whose type is your machine interface, and want to directly access the field. When in rome, act like romans. When programming java, act like other java programmers. Which means: Don't treat fields as interface - as API. If the very essence of 'a machine' (that is to say: An object that is an instance of a class, and that class implements machine) is that it can provide a list of integers representing the temp concept, then make that part of the interface: Write Vector<Integer> getTemp; in the interface, and let each implementing class provide an implementation. If you expect that all implementing classes likely just want:

private Vector<Integer> temp;

public Vector<Integer> getTemp() {
  return temp;
}

Then you can put that in an abstract class which implements the interface, and have all your impls implement the abstract class.

If this is all flying over your head, I can make it simpler:

  • All field decls in interfaces are necessarily public static final, whether you write it or not. You can't declare fields that aren't, the language simply won't let you.
  • There are good reasons for that - see the above explanation.

NB:

You appear to be using some extremely outdated (at least 25 years at this point!!) guidebook. This code wouldn't pass any review as a consequence. Vector is obsolete and should not be used, and has been obsolete for 20 years: You want ArrayList, presumably. Java conventions dictate that TypesGoLikeThis, methodNamesLikeThis, variableNamesAlsoLikeThis, and CONSTANTS_LIKE_THIS. Thus, it'd be public interface Machine, not public interface machine. The compiler lets you do whatever you want, but your code is needlessly weird and inconvenient when you integrate it with any other java code if you fail to follow the conventions.

CodePudding user response:

As per my understanding you can't do it, because interface variables are static final hence you have to initialize in interface itself.

  • Related