• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • paul wheaton
  • Ron McLeod
  • Devaka Cooray
Sheriffs:
  • Jeanne Boyarsky
  • Liutauras Vilda
  • Paul Clapham
Saloon Keepers:
  • Tim Holloway
  • Carey Brown
  • Piet Souris
Bartenders:

The same old Interface reference type issue

 
Ranch Hand
Posts: 178
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Source: Inquisition



I thought this would work fine... But the answer is "Compile time error at line 1 and it will compile if that line includes a cast for face"

This is what I thought: 'test' does not implement 'face'. But, there could be a scenario in the future wherein some class could extend 'test' AND implement 'face'. So, the compiler would allow Line 1 to be compiled, and at runtime also, 'test_one' actually points to a 'tester' object that indeed implements 'face' and hence, runtime exception also will not occur.

Where have I gone wrong?
 
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well it's an idiosyncrasy of the compiler implementation i guess.

Look at the following modified code:


I guess when assigning objects to references using assignment(=) operator the compiler checks for the actual type of the object being assigned.

Thus, when you say,

face f = test_one;

The compiler says, well test_one is of type *test* and since test does not implement *face* so i can't allow this assignment.

but when you say,

boolean b = test_one instanceof face;

Then the compiler says well, may be at run time it might turn out that *test_one* actually refers to an object which does implement *face*. Which actually is the case.

But weirdly, the compiler also gives the same benefit of doubt to the following:

boolean b1 = new test() instanceof face;

Conclusion: The compiler does not work the same when using instanceof operator as it does when using assignment(=) operator.

That's strange but i guess the key here is to look for whether you are making an explicit assignment because an assignment is more dangerous than the use instanceof operator. The reason being you would anyhow be doing something or the other based on the boolean result returned by the instanceof. So maybe compiler is less strict with the instanceof operator.

Well, i am just thinking aloud i guess. Anybody feels i am wrong then please do correct me.
[ December 01, 2008: Message edited by: Harvinder Thakur ]
 
Rekha Srinath
Ranch Hand
Posts: 178
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ya I kind of understand Harvinder...But not 100% clear..
Lets see what others have to say as well..
 
Ranch Hand
Posts: 1710
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

Your scenario is something like:

class Animal{
}

class Dog extends Animal{
}

class Cat extends Animal{
}

Dog d = new Dog();
Cat c = d; // Compiler Error

Its true that Dog and Cat both extend Animal. But there is no relation
between these two classes. Both are siblings extending same parent class.
 
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Another example: with the same reference, the below code will cause compiler error at line 3.

And this will compile properly
 
Duc Vo
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Harvinder Thakur:

face f = test_one;

boolean b = test_one instanceof face;

boolean b1 = new test() instanceof face;


Not quite right though, in the above, b will be true and b1 will be false. It is perfectly legal since instanceof is just checking if an object is assignable to another class.
[ November 30, 2008: Message edited by: Duc Vo ]
 
Ranch Hand
Posts: 509
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
interface I { void meth(); }
class B extends A implements I
{ public void meth(){System.out.println("hello");}}

class A
{
public static void main( String args[] )
{
A a = new B();
I i = (I)a; // 1
i.meth();

}
}

Line 1, explicit casting to I is required.
 
Harvinder Thakur
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Duc Vo:

Not quite right though, in the above, b will be true and b1 will be false. It is perfectly legal since instanceof is just checking if an object is assignable to another class.



Let me make myself clear.

Firstly, b will be true and b1 will be false at runtime. I never refuted that and i completely agree with it.

The point i am trying to make is the behaviour of the compiler which means compile time behaviour and not run time behaviour.

So, when i say that,



but,

and, if i say,



but,




i am trying to highlight the difference between how the compiler behaves in the above mentioned scenarios. right.

So, IMHO the compiler does a stricter check incase of assignment(=) operator and is a bit lenient for instanceof operator because above in one case the compiler could have easily detected that *test* is not implementing *face*:

boolean b = new test() instanceof face;

I hope i make sense...
 
Duc Vo
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Harvinder Thakur:

I hope i make sense...


Yes, you made sense. But what I meant is that your comparison is not quite right. You are comparing logical operator (instanceof) to a an assignment operator (=). The compiler treaments for logical operators (if it is true) and assignment operator (assign its reference/value from one to another) are very different.
 
Harvinder Thakur
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well i tried to put the instanceof operator in the fray because

Originally posted by Rekha:
But, there could be a scenario in the future wherein some class could extend 'test' AND implement 'face'.



as per the above quote i thought Rekha was confused with the use of *instanceof* operator and *assignment* operator, because her assumption holds true incase of instanceof operator and not assignment operator.

Well, maybe Rekha may correct me by showing an example that her assumption works in certain scenarios using assignment operator. Right now i am not able to think of that. :roll:

So, fellow ranchers please do correct me with your valuable inputs.
 
Sheriff
Posts: 9708
43
Android Google Web Toolkit Hibernate IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
well harvinder came very close to ending this thread very early. Now let me try

Well if you write this code



if the compiler would allow this, and the actual object to which the reference b points to is-not-a Interface, then you will have a ClassCastException at your hand. So the compiler cannot allow you to skip the cast as it cannot claim the blame of the runtime exception. It forces you to use the cast as if any exception comes, you know that you had used a cast.

In case of instanceof, the compiler is lenient as the real use of instanceof is indeed test the actual runtime type of the objects. If it would force you to use a cast when you test this

b instanceof Interface

like

((Interface)b) instanceof Interface

then the instance of comparison is of no use as the cast will only be successful if b is-a Interface. So basically if the cast was mandatory, then you will only have two possible answers 1) true 2) ClassCastException...
 
Harvinder Thakur
Ranch Hand
Posts: 231
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I fully agree with Ankit
 
Rekha Srinath
Ranch Hand
Posts: 178
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
All,

Thanks for brainstorming ... I have now got a better idea than before ...
reply
    Bookmark Topic Watch Topic
  • New Topic