File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Java in General and the fly likes inner class generics issue Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Soft Skills this week in the Jobs Discussion forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "inner class generics issue" Watch "inner class generics issue" New topic
Author

inner class generics issue

Marcus Kelvin
Ranch Hand

Joined: Jan 04, 2012
Posts: 44
I'm trying to extend LinkedList by overriding the listIterator() method to return a customized iterator, which is created by an inner class extending ListIterator.



Ideally, I wanted to do this by accessing the enclosing class's get(), etc. methods. But:



But what happens is I get told:



This means I instead have to pass the list instance into the iterator constructor and make it a private variable, so I can go:



etc. Seems a little stupid. Does this mean it is impossible to access generically typed fields, methods, etc from an inner class matching the type of the enclosing class?
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3611
    
  60

So you need to access the instance of the outer class? See http://www.coderanch.com/t/573871/java/java/Inner-classes-pointer-parent#2612252
Marcus Kelvin
Ranch Hand

Joined: Jan 04, 2012
Posts: 44
Martin Vajsar wrote:So you need to access the instance of the outer class? See ....


I can access the instance of the outer class. That is not the problem. In plainer language: the inner class implements ListIterator<T>, therefore its next() method must return an item of type T. I want to get this by calling get(), which implicitly belongs to the outer instance (a LinkedList derived object) and returns an item of type T. But the compiler says the T of the inner instance cannot be considered the same as the T of the outer instance, therefore I cannot meaningfully make use of the access to the outer instance -- instead, I have to pass it in and work with that reference:



Using list.get() works, because the compiler is fine with the fact that it returns type T. But if I just use get() (method of the instance of the outer class) the compiler sees it as a type mismatch, so I cannot make meaningful use of that access. The "inner class" might as well be a completely separate class. Make sense?
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3611
    
  60

Oh, I'm sorry, I was not paying enough attention.

By declaring your iterator class as CircularIterator<E>, you're introducing a new type parameter E, which, though it has the same name, has no relation to the type parameter E of the outer class. So the solution is to simply not declare the parameter in the CircularIterator class definition; that way the E (which is valid throughout the source code, including any inner classes) will be the E of the outer class.

You might want to try to take a look at the LinkedList source, to see how it is handled there.
Marcus Kelvin
Ranch Hand

Joined: Jan 04, 2012
Posts: 44
Martin Vajsar wrote:So the solution is to simply not declare the parameter in the CircularIterator class definition; that way the E (which is valid throughout the source code, including any inner classes) will be the E of the outer class.


That works, I just get a bunch of "unchecked conversion" warnings I guess I need to suppress. The constructor is private, so that shouldn't matter.

Thanks.
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3611
    
  60

Marcus Kelvin wrote:That works, I just get a bunch of "unchecked conversion" warnings I guess I need to suppress. The constructor is private, so that shouldn't matter.

Thanks.

You're welcome

Still, I'd expect that to compile clean. Could you post more of the code, just enough for the warnings to be seen?
Marcus Kelvin
Ranch Hand

Joined: Jan 04, 2012
Posts: 44
Martin Vajsar wrote:
Still, I'd expect that to compile clean. Could you post more of the code, just enough for the warnings to be seen?


Sure. I haven't tested this yet as I only finished it a minute ago, but it compiles and I think the general idea is clear:

Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4489
    
    8

I haven't tried it, but can you declare CircularIterator implements ListIterator<T>? It feels like that ought to be allowed, because the CircularIterator always sits within a CircularList<T>. And if it works you've got a fully generic solution and you won't get the warnings.
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3611
    
  60

The line 27 of your code should look like this instead:

This is the way to "force" the outer T parameter over the CircularIterator class. You'll have to change a few method declarations inside the inner class to take/return T instead of Object, but then it should compile without warnings.

It should not take much time to understand what's happening here. Once you do, you'll understand generics a tad better again.
Marcus Kelvin
Ranch Hand

Joined: Jan 04, 2012
Posts: 44
"CircularIterator implements ListIterator<T>" did the trick, thanks gang.

Martin Vajsar wrote:You'll have to change a few method declarations inside the inner class to take/return T instead of Object,


Actually, the issue there was that add(T) clashed with the outer class's add() method, whereas add(Object) did not but still satisfied the ListIterator interface requirement. Interestingly, this last change seems to have mitigated that problem as well -- now add(T) is fine. Not quite sure why that would make a difference but
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: inner class generics issue