wood burning stoves 2.0*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes ExamLab Generic Question Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "ExamLab Generic Question" Watch "ExamLab Generic Question" New topic
Author

ExamLab Generic Question

Rageni Kalra
Greenhorn

Joined: Jan 29, 2014
Posts: 10
Hi,

I found this question in Examlab and I am very confused with Generics after attempting this question. I found some old threads on this community for this question but none had a proper explanation.
Can anyone explain me why #1 compiles and #2 does not?



I tried a simpler version also :


and here also 3 - compiles while 4- does not .

Did you guys faced Generic questions of this complexity in the real exam?
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1000
    
  16
Rageni Kalra wrote:
Can anyone explain me why #1 compiles and #2 does not?



I tried a simpler version also :


and here also 3 - compiles while 4- does not .


Both of those compile in Java 6, 7, and 8.

When you create a class as follows,



K has a special meaning in that class definition. K is a type that extends java.lang.Number.

You can have class definitions such as the following, for example.



Now, when you create a method, as follows, in such a class--


or as
,
the <K> that you specify before the return type hides the type K that has a special meaning for this class.

public abstract <K> ABS<? super Number> useMe(ABS<? extends K> k);

Note that this K is a different K. It is not the same K that you declared while creating the class. I guess this is not what you wanted.

You don't require that <K> there cause you have already specified what K means in your class declaration statement. And it's wrong cause the <K> that you have put before the return type in the method declaration statement is a completely different ( and independent ) K. I guess this wasn't the intended behavior.

Edit : But, like I said, those would still compile.
Rageni Kalra
Greenhorn

Joined: Jan 29, 2014
Posts: 10
thanks Chan Ag but i understand the overshadowing concept of K, my question is why #1 compiles and #2 does not?
Both have K(say k1 for reference) in method shadowing the K (say k2) in the class declaration.

Neither (ABS<? super K>) nor (ABS<? extends K>) [ here K is k1]
has any relation with (K extends Number) [here K is k2]
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1000
    
  16
Rageni Kalra wrote:thanks Chan Ag but i understand the overshadowing concept of K, my question is why #1 compiles and #2 does not?
Both have K(say k1 for reference) in method shadowing the K (say k2) in the class declaration.



But, they both compile without compilation errors ( albeit with warnings ) for me.
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1000
    
  16
Ok, so this gives compilation errors, if I compile it on the command line.
In the eclipse, it works fine.

Let me take a look.
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1000
    
  16
First of all, thanks for pointing out my mistake.

I only have half answers as of now. I still have to look into JLS to substantiate my answer.

So if I am responding to this, it'll have to wait. Sorry.
Rageni Kalra
Greenhorn

Joined: Jan 29, 2014
Posts: 10
No Problem. Thanks for replying. I will wait for your answer.
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1000
    
  16
Now here is a weird thing. Yesterday while I was working on it from home, it was giving me compilation error for cases that had ABS<? extends K> anywhere ( either as return type or arguments ) in the methods if I compiled my source file from the command line. I was using the Java 8 compiler.

The reason was that the parameter <K> for the method could be anything, even Object and hence ABS< anything that extends Object> was not within the bounds for the class type ( upper bound = Number ).
But for the cases that had ABS<? super K> anywhere ( either as return type or arguments ), the parameter <K> was resolved to Number, not Object.

I couldn't find anything in the JLS last night that explained why. I have vague reasons but I'd better keep them to myself cause they are sort of retrofitted reasons after seeing the behavior... more along the lines of probably X, or probably Y.

On Eclipse ( javac 1.8 ), it compiled successfully. I don't know why.

As far as I remember, last night I had tried it with JDK 1.7 also and the behavior was the same.

But today, I compiled the following file from command line ( JDK 1.6) and it compiled successfully for me.



Obviously the compilation didn't fail in the eclipse.

Now I'm more confused than ever.

All I'll going to do is try this one later ... much later, with all the versions of JDK >= 1.6 once more, cause like you, now I need to know the answer for myself too.

For the not compiling successfully behavior, the weird thing is the compiler is partial. It is smart in the case of <? super K> but unsmart in the case of <? extends K>. Or smart in the case of <? extends K> and unsmart in the case of <? super K>. But there must be a reason that I can't see currently. I can't even find anything mentioned about it in the JLS also. Or I just didn't look properly.

My ( probably stupid ) reason for now is that when we have a class <K extends Number>, the upper bound for the class type is Number. So we can't have a different <? extends P> in the method argument with parameter

cause P could be anything, even Object. That wouldn't fall within the class upper bound, i.e Number.
But I can't understand why this same logic does not apply for <? super K> case. Here the parameter of the method is resolved to <Number>, not <Object>, which I think is weird.

Rageni Kalra
Greenhorn

Joined: Jan 29, 2014
Posts: 10
Thanks for trying Chan.
I hope examples like these are added in Kathy Sierra book and explained clearly.
Does anyone else know the explanation about this behavior?
Chan Ag
Bartender

Joined: Sep 06, 2012
Posts: 1000
    
  16
Finally, I think I get it partly. And a part of it is guess work.



I think we already know that the parameter of method shadows the one defined in the class and it's a different parameter. So now the compiler has to resolve it.

In method1 <P> resolves to Number cause Temp<? super Number> is more general than Temp<? super Object>.
In method2 <P? resolves to Object cause Temp<? extends Object> is more general than Temp<? extends Number>

This page has a diagram at the bottom that makes it easy to visualize this.

<Guess>
In both the cases, the equivalent code after erasure would have the type as Object. But intuitively we can imagine that in the case of <? super Number>, the compiler has the lower bound and has just limited cases to consider that it can determine are impossible as real arguments because of the class parameter. So this would be safe cause the compiler knows it is not possible to invoke this method with conflicting argument. So the compiler allows this. But in the case of <? extends Object>, the compiler can only place a higher bound check. With the only bound being that of Object and no lower bounds, it would include those cases also which are not provided by the parameter type of the class <K extends Number>.
</Guess>

Edit : And the interesting thing is the eclipse(Kepler) behaviour. It doesn't catch this compilation error. While executing this on the Command line with JDK versions 1.6.0_45 and higher, the compilation fails. With JDK 1.6.0_43 and lower the compilation succeeds.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: ExamLab Generic Question
 
Similar Threads
Confused over generics
How do you extend a generic abstract class
confused with generics
need help about generics
Examlab generics question