• Post Reply Bookmark Topic Watch Topic
  • New Topic

Why get IllegalAccessException for Iterator.next in reflection?  RSS feed

 
Dan Bizman
Ranch Hand
Posts: 387
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm using reflection to deal with a number of objects sent into my program. Everything has worked fine for every object up till now. However, when a java.util.Iterator is sent in and the method "next" called, I get the exception:



Is my only solution to call "setAccessible( true )" on the method "next" prior to invoking it? I don't like that option but it seems to be the only choice. Well, I suppose I could get the class' interfaces, loop through them and if it's public look for the method I want (and if not, call setAccessible). Both options don't seem great.

What I don't get is that the iterator returned has a public method "next" and yet in reflection somehow I'm unable to call it? That makes no sense: it's public!

[ March 31, 2008: Message edited by: Dan Bizman ]
[ March 31, 2008: Message edited by: Dan Bizman ]
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Most likely, this error message is misleading, and the problem is not with the public method, but with the non-public class java.util.AbstractList$Itr. The $ tells us that Itr is some sort of nested class defined within AbstractList. If this class is not public, then reflection won't let you access its methods, even if the methods are public. You have two basic options: (a) call setAccessible(true) on the class (not the method), or (b) use the Class instance java.util.Iterator.class (representing a public interface), rather than java.util.AbstractList$Itr (representing a non-public class). Both of these define a public method next(), but only Iterator.class will let you call its methods without using setAccessible(true).
 
Dan Bizman
Ranch Hand
Posts: 387
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jim Yingst:
Most likely, this error message is misleading, and the problem is not with the public method, but with the non-public class java.util.AbstractList$Itr. The $ tells us that Itr is some sort of nested class defined within AbstractList. If this class is not public, then reflection won't let you access its methods, even if the methods are public. You have two basic options: (a) call setAccessible(true) on the class (not the method), or (b) use the Class instance java.util.Iterator.class (representing a public interface), rather than java.util.AbstractList$Itr (representing a non-public class). Both of these define a public method next(), but only Iterator.class will let you call its methods without using setAccessible(true).



Thanks for the response.

I can't use "Iterator" as I don't know the class of the objects coming in, it's all through reflection, so this is just one case. I can't predict beforehand what it'll be. So I guess I'll do the setAccessible...

I have a question however: why do i call setAccessible() on the class and not the method? It does work to call it on the method, so is this bad for a reason?

Thanks!
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[Dan]: I can't use "Iterator" as I don't know the class of the objects coming in, it's all through reflection, so this is just one case. I can't predict beforehand what it'll be. So I guess I'll do the setAccessible...

Another possibility is to use Class methods getSuperclass() and getInterfaces() to discover all classes and interfaces that are extended or implemented, and if one of those is public and declares the method you're trying to use, use that class/interface instead. On the other hand if using setAccessible() works for you, that's probably easier.

[Dan]: I have a question however: why do i call setAccessible() on the class and not the method? It does work to call it on the method, so is this bad for a reason?

Well, if that works, then do it. I'm working from vague memories of a problem I saw long ago. Maybe I'm misremembering, or maybe the JDK behaves differently now. For the problem I'm remembering, the root cause was that the class was non-public, so it makes at least intuitive sense to modify the class to be accessible, not the method. But hey, whatever works.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!