• Post Reply Bookmark Topic Watch Topic
  • New Topic

Resurrecting Method Local Inner Class?  RSS feed

 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

Sorry if I've posted this in the wrong forum, but I figured this would qualify as the beginner's question, so I posted it here.

I know that a method local inner class (MLI class) can use the variables in it's enclosing methods, only if those variables are declared final. The reason, from what I've understood so far, is that the object of MLI class can live longer than the local variables, hence the copy of the final variable is stored in this MLI class's object, so the variable can still be used by this object if/when this object is passed out of this method. I hope this is correct so far.

So what I did is, I tried passing the MLI class's object in the outer class's method and also tried serializing the MLI class's object. I wanted to see if we can resurrect this MLI class's object and access that final variable, which is said to be "stored" with this object. The thing is, I don't know how to access it. I got as far as getting the name of the class through outside method. But when I tried typecasting it, it gives error. I understand that there'd be some more complex syntax for doing all this... but I don't know what. Can anyone please guide me about this? Here's the code that I'm trying out. I'm trying to know what's the use of passing the MLI class's object outside the method and how to access it from the method we're passing it to. Any ideas/suggestions will be appreciated. Thanks in advance. Here's the code -

 
Campbell Ritchie
Marshal
Posts: 56570
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Roshni Singhania:
Hi,

Sorry if I've posted this in the wrong forum, but I figured this would qualify as the beginner's question.
Congratulations. You are the first person for ages I have seen post what I think is an advanced question. Off to advanced you go!
 
amitabh mehra
Ranch Hand
Posts: 98
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
have no concrete idea.. but just played along with your sample code. Tried the following:

added a new method in class MLI:



Later in show(), added the following:


This returned the value of the variable i that was set. Is this approach valid?
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wow! Thanks!

So anyone ever come across this scenario involving inner classes? If a method local inner class object can access a final variable in its enclosing method and this object can be passed out of this method.. there ought to be a way to access/use this object right? I've been trying various syntax/casting etc.. but still haven't found any way!
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


What's that "Method" at the beginning? It gave me compile-time error when I tried adding the first line of above code.

Edit: Ok, I googled. It's a class. I didn't know about it. Will try it out.
[ May 25, 2008: Message edited by: Roshni Singhania ]
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
amitabh mehra, thanks for taking time to help me with my problem. I'm learning about this Method class for the first time. I added the code you gave to my class and only changed the part where you've used



to the name of existing method as



It's working.. this is what I wanted to know.. how to access/use the Method Local Inner class object outside that method. So thanks a lot for the guidance.

One more small problem - the program runs and displays the value of i and in the end gives NullPointerException. Why is that?

This is what I got from Sun's documentation -

If the underlying method is static, then the specified obj argument is ignored. It may be null.

Otherwise, the method is an instance method. If the specified object argument is null, the invocation throws a NullPointerException. Otherwise, if the specified object argument is not an instance of the class or interface declaring the underlying method (or of a subclass or implementor thereof) the invocation throws an IllegalArgumentException.


I don't entirely understand the part in bold. What exactly is "object argument"? When do we pass "null" as object argument and what else can pass there, other than null?

Edit: What's this line for -


[ May 25, 2008: Message edited by: Roshni Singhania ]
 
Rob Spoor
Sheriff
Posts: 21135
87
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's useless. Most IDEs will warn you about an unused variable.

Somehow I think that Roshni meant to use it as second parameter to the invoke method.
 
Henry Wong
author
Sheriff
Posts: 23295
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But when I tried typecasting it, it gives error. I understand that there'd be some more complex syntax for doing all this... but I don't know what. Can anyone please guide me about this?


Unfortunately, in order to cast it (to the full implementation class type), the class must be in scope. And for method inner classes, they are not in scope outside of the method. So, the best you can do is cast it to any interface implemented by inner class, and any super class of the inner class, provided that they are in scope, of course.

Henry
 
amitabh mehra
Ranch Hand
Posts: 98
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roshini, the line :
Object o[] = null;
is not needed. Was trying something else and by mistake left it there.

For NullPointerException, make sure that your method on which you are calling invoke and the class reference that you are passing as 1st arg are not null and valid.

For the bold part in your comment, as far as I could interpret, it means that the first argument to the method invoke() should be a valid instance of the interface/class or any subclass which is implementing the method which you want to invoke.

For example, if i have another class C and in this call to the method invoke in your code, i pass a reference of C, during run time it will give:

java.lang.IllegalArgumentException: object is not an instance of declaring class
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First of all, thanks to all the people who have taken time to help me solve my problem. I appreciate all your help!

For the bold part in your comment, as far as I could interpret, it means that the first argument to the method invoke() should be a valid instance of the interface/class or any subclass which is implementing the method which you want to invoke.

For example, if i have another class C and in this call to the method invoke in your code, i pass a reference of C, during run time it will give:

java.lang.IllegalArgumentException: object is not an instance of declaring class


Ok, I think I'm somewhat getting it - let me see if what I've understood is correct.. this IllegalArgumentException is basically thrown here, if the class of the object we're passing as the first argument to "invoke" method, is NOT the actual class or NOT "related" to the actual class by inheritance. As in, the class of the object passed as the first argument to the "invoke" method" can be a subclass of the actual class/interface, am I right or wrong?


Also about the following part -

For NullPointerException, make sure that your method on which you are calling invoke and the class reference that you are passing as 1st arg are not null and valid.


So NullPointerException in this case is only about the first argument? Then what about the second argument? What exactly is the second argument (which you've passed as "null")? I tried removing the second argument altogether and running the code as follows -



But the result I get upon running this code is the same as the one where we provide the second "null" argument -



I get "NullPointerException" in both cases and I'm not clear as to what exactly is throwing this exception.

Edit: Corrected some grammatical errors (which were entirely changing the meaning of a statement).
[ May 26, 2008: Message edited by: Roshni Singhania ]
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Henry Wong:


Unfortunately, in order to cast it (to the full implementation class type), the class must be in scope. And for method inner classes, they are not in scope outside of the method. So, the best you can do is cast it to any interface implemented by inner class, and any super class of the inner class, provided that they are in scope, of course.

Henry


But if I've implemented some method in my Method Local Inner class, then the interface or the super class it's implementing, won't possibly be able to invoke that method right? Because superclass/interface won't know about the implementation in its subclass.
 
amitabh mehra
Ranch Hand
Posts: 98
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As in, the class of the object passed as the first argument to the "invoke" method" can be a subclass of the actual class/interface, am I right or wrong?

Yes, you are right.


Then what about the second argument? What exactly is the second argument (which you've passed as "null")?

This is an array of arguments which the method you are trying to call, expects i.e. its formal parameters. In your case, there was no parameter, so null. Check the )]javadocfor complete explanation.


I get "NullPointerException" in both cases and I'm not clear as to what exactly is throwing this exception.

This is because you are calling goMLI() which is void and expecting an int while assigning to your integer variable.

Apart from this, I tried serializing and deserializing seperately i.e, in two different runs. And during second run I also changed the value of the final int i in method go(). But the output showed the new changed value when it should have shown the one that my de-serialized object had (if it had any??).

I tried the following code in class MLI:


and again did serialization and de-serialization sepreately. In readObject() it printed the correct de-serialized value. But integer returned from invoke method was the new value.

Sorry, I am lost on this . Can someone help on this?
[ May 26, 2008: Message edited by: amitabh mehra ]
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is an array of arguments which the method you are trying to call, expects i.e. its formal parameters. In your case, there was no parameter, so null. Check the )]javadocfor complete explanation.


Yes, I'd read the javadoc for Method class yesterday itself, but I somehow jumbled up the words in the description and kept thinking that it was about passing parameters to the object, which confused me. It's about passing the parameters to the method being invoked. Didn't read properly before, my mistake! Ok, now I'm clear about that part.


quote:
I get "NullPointerException" in both cases and I'm not clear as to what exactly is throwing this exception.


This is because you are calling goMLI() which is void and expecting an int while assigning to your integer variable.


Ok, now I get it! I made the change in that line accordingly (to suit the void return type) as follows -



On compiling this, I got a warning as follows -



It executed successfully though.

Then I removed the second argument as follows -



And above compiled and executed without any error. So providing the second argument to the "invoke" method is optional (when we don't have any parameters to pass, of course)?
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I was just wondering - We've so far been trying to access a local variable "int i" from this method local inner class, after its method was over. When a method local inner class accesses/uses a final variable of its enclosing method, where/how is that variable stored in this method local inner class? What does it mean exactly that the value of final variable is captured in the MLI class object? Is it something like JVM implicitly declares and allots space (in a method local inner class object), for a final, local variable (as int i=10) when this MLI object tries to access this variable? So that this variable then becomes a part of the inner class as a local (or a class???) variable? What exactly goes on there?
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by amitabh mehra:

Apart from this, I tried serializing and deserializing seperately i.e, in two different runs. And during second run I also changed the value of the final int i in method go(). But the output showed the new changed value when it should have shown the one that my de-serialized object had (if it had any??).

I tried the following code in class MLI:


and again did serialization and de-serialization sepreately. In readObject() it printed the correct de-serialized value. But integer returned from invoke method was the new value.

Sorry, I am lost on this . Can someone help on this?

[ May 26, 2008: Message edited by: amitabh mehra ]



Hey, yeah, I also tried writing a new code, serializing and deserializing separately in two different runs. I had the same problem.. it's showing the changed value. So I wrote deserialization code in a separate file and executed it from a separate folder (containing only deserialization code and the .ser file) and then I got the ClassNotFoundException for both the outer and the MLI class. When I put both these class files in that separate folder, then only it worked. So apparently, class files are also required while deserializing. And if the class files are there, then it'll get the updated value only. Till now, I was thinking that only the .ser file is enough. And would've continued to think so unless you'd brought this up.

Here's the exception I got when I tried deserializing without the outer class and MLI class files -



That's the problem you were talking about, right?
[ May 26, 2008: Message edited by: Roshni Singhania ]
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!