What happens to variables/objects in inner classes of function objects?

Multi tool use
Multi tool use


What happens to variables/objects in inner classes of function objects?



I have a function multi2 which returns inner class Inner as an Object.


multi2


Inner


Object



What happens to a - where is it saved and how can I access it?


a


public class C {
private static Object multi2(final int a) {
class Inner {
public int hashCode() {
return 2*a;
}
}
return new Inner(); // What happens to a?
// Who allocates a?
// Can I Access a?
}

public static void main(String args) {
Object o = multi2(6);
System.out.println("o.hashCode() = " + o.hashCode());

o = multi2(4);
System.out.println("o.hashCode() = " + o.hashCode());
}
}




5 Answers
5



What happens at the implementation level is that a copy of the value of a is saved in a synthetic instance variable declared in the compiled version of the C.Inner class.


a


C.Inner



The value of a is passed to the compiled Inner constructor via an extra parameter.


a


Inner



The C.Inner.hashCode method uses the value of the synthetic variable. Accessing a in the source code of Inner.hashCode is transformed into accessing the corresponding synthetic variable in the compiled code.


C.Inner.hashCode


a


Inner.hashCode



The variable in the outer scope must be final1. The synthetic variable must be final2 in the Inner class. This maintains the illusion that (potentially) multiple instances of the Inner class are seeing the same a variable. (They aren't, but since the variable(s) can't be changed, it is not possible for the code of the inner class to tell the difference.)


final


final


Inner


Inner


a



If you use javap to look at the bytecodes for the compiled example, you will see the mechanisms used to implement this in the outer and the inner classes.


javap



1 - or effectively final from Java 8 onwards.



2 - If a could be mutated by an Inner method, then two Inner instances with the same outer class need to share a mutable variable whose lifetime is (now) longer than the stackframe for a multi2 call. That entails somehow turning a from stack variable into something that lives on the heap. It would be expensive and complicated.


a


Inner


Inner


multi2


a





Great, can you add an explanation about trying to access a variable, like @Clayton answer.
– Dennis Vash
Jul 2 at 12:51


a



You have defined the class Inner inside the function so the scope of the class will be
restricted with in the method. And your function is static so it will be live as long as the class definition is loaded. You have override the hashCode function inside the InnerClass so every time you are calling the multi2(param) you are creating the hashCode for the instance of InnerClass and returning the instance of the InnerClass.


class Inner


multi2(param)



So as for you questions, please correct me if i am wrong.



What happens to a ?
a is with in the scope of your static method, so it will be live as long as the class definition is loaded.


a



Who allocates a?
scope of a is restricted inside the static method and static method does not require instance to access it but as for the static method/variable allocation, i think it depends on JVM.


a



Can I Access a?
No you cannot access a from outside you static method, it is restricted with in your static method.


a



Since the "a" is a local parameter, you could use a different approach to read the "a" value:


public class C {

public static Object multi2(final int a) {
return new Inner(a);
}

public static void main(String args) {
Object o = multi2(6);
System.out.println("o.hashCode() = " + o.hashCode());
System.out.println("o.getA() = " + ((Inner) o).getA());

o = multi2(4);
System.out.println("o.hashCode() = " + o.hashCode());
System.out.println("o.getA() = " + ((Inner) o).getA());
}
}

class Inner{
public int valueA;

public Inner(int a)
{
valueA = a;
}

public int getA() {
return valueA;
}

public int hashCode() {
return 2*valueA;
}
}



I wanted to know what was actually happening, so I compiled your code and looked at the bytecode output.



Basically what happens is the compiler adds in a constructor to your class 'Inner'. It also adds a single parameter to that constructor which takes 'a'. If your multi2() method was NOT static then there would probably also be a parameter to take 'this' where 'this' is the instance of 'C' that multi2() is executing on. BUT since we're in static context, there is no 'this'.



The compiler adds a private final field to your class 'Inner' and sets that private field using the value passed via the constructor. The compiler also converts


new Inner()



into


new Inner(a)



Hashcode then accesses the private field containing the value for a.



If 'a' was an object instead of a primitive, then it would be the same way, but a reference would be passed through instead of an actual number value.



How do you access this variable? Well you access it with reflections, but there are many problems:



1) You don't know the name of the field made by the compiler, so you can only get the name by looking at the bytecode. Don't trust decompilers as they might change the name. You gotta look at the bytecode yourself to find out.



2) The compiler probably marks the field as final, which means even if you can get reflections to access the field for you, you won't be able to update it.



3) It is entirely up to the compiler to figure out field names. Field names could change between builds depending on the compiler and it's mood.



Inner is a so called local class. a is a parameter passed to the method multi2 and accessable within that scope. Outside of that method, you cannot access a.


a


multi2


a






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

OySzuPrxJ,dq89d9uD Ibsh KvPcFG0gP3
vhwkYycQj46imbxOKei 7qck36z grPq,eD6zX75w4wXW2eAYe 8,Y2 QOYu JwQ Gj5tX uBBxAbGx,4wf2xepO96sREzixO

Popular posts from this blog

PHP contact form sending but not receiving emails

Do graphics cards have individual ID by which single devices can be distinguished?

Create weekly swift ios local notifications