Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Beginner Array of Objects Confusion

Tags:

I am having trouble understanding what is actually happening when I declare the array in the following code.

class Type1 {

}

class Type2 extends Type1 {
    public void method2() {

    }
}

class Test {
    public static void main(String[] args) {

        Type1[] x = new Type2[2];
        x[0] = new Type1(); // runtime error
        x[1] = new Type2();
        x[1].method2(); // syntax error

    }
}

I thought since the right-hand side of the array declaration is new Type2[2] that the array would consist of reference variables of the type Type2. If this is true, the first error makes sense because I cannot have a subtype referring to a supertype.

However, why does the second error occur two lines after that? Isn't method2() known by Type2, so the method is known by the reference variable? It seems it is because Type1 doesn't know method2, so does that mean the array consists of reference variables of the type Type1? If this is true, why does the first error occur as it is no longer a subtype referring to a supertype?

Also, why is the first error a runtime error while the other is a syntax error?

Please note I am only in my second programming course, so my terminology may be a little off.

Edit: The question here does not answer my question because it does not answer why an element of an array like x cannot invoke method2() even though an element of x of Type 2. My question is different because of this and because my question also asks why the first error occurs when the second error also occurs (why an element of x cannot refer to and object of the type Type1 and at the same time cannot invoke method2()). I originally thought that if one error occurred, then the other cannot occur. I wanted a comparison between the two errors and a more in-depth explanation than simply the rules of polymorphism.

like image 784
Lindstorm Avatar asked Feb 17 '18 09:02

Lindstorm


People also ask

Why is it usually better to work with objects instead of arrays to store a collection of records?

Objects represent a special data type that is mutable and can be used to store a collection of data (rather than just a single value). Arrays are a special type of variable that is also mutable and can also be used to store a list of values.

What is the difference between objects and arrays?

Arrays are objects only in javascript. The major difference is that they store the data in an ordered collection in which the data can be accessed using a numerical index. They are also mutable and data can be modified at any index.

What is the difference between object and array in PHP?

An object is an instance of a class. It is simply a specimen of a class and has memory allocated. Array is the data structure that stores one or more similar type of values in a single name but associative array is different from a simple PHP array.

What do you mean by array of objects?

An array of objects, all of whose elements are of the same class, can be declared just as an array of any built-in type. Each element of the array is an object of that class. Being able to declare arrays of objects in this way underscores the fact that a class is similar to a type.


2 Answers

This is one of those weird things that Java allows you to do, assigning an array of a derived class to a variable of array of the base class.

In your code, x at compile time is of type Type1[]. That's what the compiler thinks it is. At runtime, x is of type Type2[], but the compiler does not know that.

The first error occurs at runtime because as you said, you can't assign Type1 to a variable of type Type2.

But the second error occurs at compile time because the compiler still thinks that x is of type Type1, and there is no method called method2 in Type1, even though x actually holds a Type2[] at runtime.

To call method2, you need to tell the compiler that x[1] is of type Type2 by casting:

((Type2)x[1]).method2();

Lesson of the day? Don't do this:

Superclass[] array = new Subclass[2];

You'll get yourself in trouble.

like image 191
Sweeper Avatar answered Sep 21 '22 11:09

Sweeper


A super-type reference can refer to a sub-type. I think you understand this, since the first error is coherent to you.

The second error stems from the fact that at compile time, x is still a Type1[]. This means that at run-time the reference can hold any sub-type, including a type that doesn't have the method method2. That's why you can only use the methods defined in Type1.

You could, for example, check whether the type is actually Type2 at runtime using isInstanceOf, and then cast it to a Type2 and then use method2. There are usually better solutions, though.

like image 24
Kraylog Avatar answered Sep 19 '22 11:09

Kraylog