Reputation: 314
I know what is going on inside of my code, and how to fix an error. However, I do not understand why things happen the way they do. Specifically, why my method returns interface List instead of ArrayList interface implementation?
What confuses me the most is after implementing moons
as ArrayList
, it still returns the interface.
Thanks in advance!
private static ArrayList<HeavenlyBody> makingSetOfMoons(){
List<HeavenlyBody> moons = new ArrayList<>();
for(HeavenlyBody planet : Main.planets){
moons.addAll(planet.getSatellites());
}
return moons;
}
Error output:
Incompatible types. Found: 'java.util.List<com.practice.HeavenlyBody>', required: 'java.util.ArrayList<com.practice.HeavenlyBody>'
Upvotes: 1
Views: 416
Reputation: 285405
Let's look at your method declaration:
private static ArrayList<HeavenlyBody> makingSetOfMoons(){
Java expects the method to return an ArrayList<HeavenlyBody>
But you return the moons variable which is declared:
List<HeavenlyBody> moons = ....
It doesn't matter what type of List subtype that you assign to the variable -- Java sees the variable as a List<HeavenlyBody>
, pure and simple. Even if you assign an ArrayList<HeavenlyBody>
to this variable, the Java compiler cannot use this to do an automatic implicit cast for you, because you could later in the method change the object that the variable refers to, now or later, and this could cause problems. As Jon Skeet states here:
The compiler uses the declared type of the variable to know how it can be used... it's as simple as that.
One solution is to change the moons variable to:
ArrayList<HeavenlyBody> moons = ...
This would work but would be wrong since it is almost always better to "code to the interface" (see: What does it mean to “program to an interface”?). Better to change the return type expected by the method in its declaration:
private static List<HeavenlyBody> makingSetOfMoons() {
This all gets down to the difference between a reference variable and a reference (or object), specifically the type of each. It is a fine distinction but an important one.
The variable and its type:
List<HeavenlyBody> moons
This variable is a reference variable that refers to an object, as opposed to a primitive variable that refers to a primitive type.
Currently you assign this reference to the variable:
new ArrayList<>();
and so the type of the variable is List<HeavenlyBody>
and the type of the reference that it refers to is ArrayList<HeavenlyBody>
Upvotes: 1
Reputation: 11120
Important thing that you seem to be missing in your understanding is two parts of the following expression:
Type identifier = new SubType();
Beware, that identifier
is a variable of type Type
(and not directly of type SubType
), and it can store a reference to the object of any other type, as long as that "other" type is a subtype of Type
(including Type
itself, as type is a sub-type of itself in Java).
Therefore:
private static ArrayList<HeavenlyBody> makingSetOfMoons() {
List<HeavenlyBody> moons = new ArrayList<>();
...
return moons;
}
will not compile, as the type of moons
is List<HeavenlyBody>
.
Q: Why this is designed so?
A: Because
in Java programming language, every variable and every expression has a type that is known at compile time.JSL - Chapter 4: Types, Values, and Variables
Imagine you had:
public ArrayList<SomeType> something(List<SomeType> list) {
...
return list;
}
You can observe, that List<SomeType> list
can accept anything that is sub-type of it; however, if you, in this case, were allowed to return list
(of type List<SomeType>
), there is a big chance you would have received a runtime exception, as not every sub-type of List<E>
can be converted to ArrayList<E>
.
Upvotes: 1
Reputation: 11
The compiler expects method to return object of type ArrayList
or more specific one (class that extends ArrayList
). However, the type of moons
variable returned from the method is less specific, i.e. List
.
In this case, it is not important for the compiler what specific type does an instance assigned to moons
variable have - the implementation you are asking about - only the variable type matters.
I hope this answers your question, if not please ask, I'll try to elaborate.
Upvotes: 1