Lukas Schmit
Lukas Schmit

Reputation: 1188

Java object casting behaving strangely

Sorry if this has come up before, but I didn't see another thread about this. But if there is one, please give me the link.

Here I have a simple program. When it runs, it prints out " 6 4 "

public static void main(String[] args) {
    Foo foo = new Foo();
    foo.t = 6;
    foo.f = 4;

    Bar b = new Foo();

    ArrayList<Bar> list = new ArrayList<Bar>();
    list.add((Bar) foo);

    Foo foo2 = (Foo) list.get(0);

    System.out.println(foo2.t + " " + foo2.f);
}

static class Bar {
    int t;
}

static class Foo extends Bar {
    int f;
}

This seems strange, because I would think that when I added the Foo it to the list, it would remove the f field, as the list holds Bars, which don't have an f.

But it seems that the f is sticking around after being casted to a Bar. Could someone explain why this is?

Upvotes: 2

Views: 310

Answers (5)

Abubakkar
Abubakkar

Reputation: 15644

In Java, fields are not polymorphic.

That's why your are confused about it.

So even if you add Foo to the list, that f is going to be there with it as its actaully an object of Foo.

Following is taken from Code Ranch - by Jim Yingst

Is that by design in Java or a limition or my misunderstanding?

It's by design. Dynamic resolution of fields would make things run a little slower, and there's really no reason to need it, since you can make fields private and access them with method, which are dynamically resolved. So fields are resolved at compile time instead.

Upvotes: 1

xvorsx
xvorsx

Reputation: 2442

It's not how polymorphism works. It doesn't remove anything from particular object. You can think about it this way:

  • there are real object in memory
  • you can have different references to this object: Foo, Bar, Object, etc.
  • real object doesn't care about references - it doesn't modified, if you create new reference
  • but each reference determine a way that you can access object by this reference.

Every instance of Foo can be treated as instance of Bar. But after explicit cast you can act with this instance as Foo again. If it was originally Bar, then this cast will fail in Runtime.

Upvotes: 2

Milind Jindal
Milind Jindal

Reputation: 176

Its like when you type cast to the Super Class variable, you just can't access the sub-class properties of the object, But the object remains intact. Just the wrapper exposing the get() and set() methods, is changed. You will not be able to see the Sub-class getter-setter method APIs. But when you type cast back to the Sub-Class (Basically unwrapping), the sub-class getter setter methods are visible to you again.

The Object being unchanged the whole time.

Upvotes: 0

ATrubka
ATrubka

Reputation: 4004

Important addition to the previous answers: Adding an object to a list does not change that object in any way. So if there was an attribute in the object it remains intact.

The rest of the confusion is a feature called polymorphism. Since Foo is Bar you can always treat it as Bar, but since Foo is a modified (extended) Bar, it may behave differently from a standard Bar object.

I hope it helps.

Upvotes: 0

Ajinkya
Ajinkya

Reputation: 22710

Even if you cast and uncast it n number of times actual object will remain same.
Casting never add / removes / changes object attributes.

Bar b = new Foo();

Here reference is of type Bar and actual object is of type Foo. As Foo extends Bar which means it have the attribute f and t (Inherited from Bar) as well.

list.add((Bar) foo);  

Here you are casting it to Bar (Upasting) but actual object is not changed.

(Foo) list.get(0);

Here you are casting it back to Foo still object is of type Foo with original values for t and f.

Upvotes: 6

Related Questions