Using Java reflection to modify nesting class's fields from inner class - java

I'm experiencing odd behavior while debugging my Java reflection homework in Eclipse.
I have 2 classes defined:
public class OuterClass{
protected Person person;
public void aPerson(Integer age) {
person = new Person(age);
}
}
public class OuterDerivedClass extends OuterClass {
public class InnerClass extends OuterClass {
public void aPerson(Integer age) {
person = new Person(age);
}
}
}
At some point in my program, I instantiated an InnerClass instance like so (using reflection as my program is supposed to work on any class. Nested classes could be either static/non-static and public/private/protected):
Class<?> outer_class = outer_instance.getClass();
Constructor<?> ctor = inner_class.getDeclaredConstructor(outer_class);
Object inner_instance = ctor.newInstance(outer_instance);
Later on I invoked the OuterDerivedClass$InnerClass.aPerson method:
method.invoke(inner_instance, parameter);
For now, it seemed like all went OK: The inner_instance was created successfully, the correct aPerson method (the one in InnerClass) was invoked. BUT, later on my program, as I tried to access the person field from outer_instance, I figured out it was still NULL (though it was created in aPerson method).
While debugging in Eclipse, I found out this:
(PersonStoryDerivedTest == OuterDerivedClass in my question).
The id of this$0 is the same as the one I sent to the constructor (outer_instance). I couldn't figure out what is the second person field (the one that apparently was created by invoking aPerson). Isn't this field supposed to exist only in the nesting class? My intention was that the invocation of OuterDerivedClass$InnerClass.aPerson would change the person field in outer_instance (I thought this is the reason why it was sent to the Constructor in the first place).
Can someone please clarify these issues? Thanks!

I couldn't figure out what is the second person field
Well, since
public class InnerClass extends OuterClass {
// ^^^^^^^^^^^^^^^^^^
your InnerClass also inherits its own person field which is set by
public void aPerson(Integer age) {
person = new Person(age);
}
because person refers to this.person and this inside this method represents instance of class where method was implemented (in InnerClass).
If you want your method to initialize OuterClass#person field you need to refer to it via OuterDerivedClass.this.person, but this will leave uninitialized person field of InnerClass.
Other (simpler) option is not extending OuterClass from InnerClass:
public class InnerClass{

Related

Questions related to Java polymorphism

public class Test{
public static void main(String[] args){
new Person().printPerson();
new Student().printPerson();
}
}
class Student extends Person{
private String getInfo(){
return"Student";
}
}
class Person{
private String getInfo(){
return "Person";
}
public void printPerson(){
System.out.println(getInfo());
}
}
I have some questions related to Student().printPerson() in the second line of the main function.
What I know is that: Java will first try to find the printPerson() in Student class. Since it couldn't find one, it will go to find the printPerson() in the superclass of Student which is Person. Now it executes the Person's printPerson() and here are my questions:
The printPerson() invokes another method getInfo(), so which getInfo will Java choose? Could you please explain with details?
Please explain how the modifiers of the getInfo() affect the output.
For your reference, If I remembered correctly. If the modifiers of both getInfo() are public, the output will be: Person Student If they are both private, the output will be Person Person
I’m on my mobile, so forgive me for grammar and typos.
Also disclaimer, I’m not heavy with java implementation so I am giving a generic explanation and I may have a few things incorrect with how java implements.
What happens is because of access level modifiers and restricting scope.
For your person class,
You have your two methods, public print and private getInfo.
You person class can see both the methods.
Your student class you have one method, private getInfo, and you extend the person class.
Because getInfo is private, it is only know to that class and nothing else. Because of this Java will not override the super (person) getInfo with the Student’s getInfo.
Because the method is not be overridden when Student.Print is being called, student.super.print is resolving to the student.super.getInfo method instead of student.getInfo.

Java Inheritance with already created superclass

Lets say i have a Super class Person and subclass Employee
I would like to create a person class first and then use it as a param to be placed into my employee class's constructor.
E.g. Public Empolyee(Person person....) (This produces a constructor not found error during compile time)
My Case scenario is that i have a Person object that has not been instantiated as an employee yet and later on i would like to use it to instantiate an Employee object and I would like to pass this person's variables over.
So how do i do this? Also please do explain if it should be done this way or not.
You directly get access to all Person class members via Employee class due to the inheritance relationship. You dont need to pass parent object to a child.
Pass all the necessary parameters to Employee and call super() from its constructor.
//Person constructor
Person(param1, param2){
}
class Employee extends Person
//Employee constructor
Employee(param1, param2){
super(param1, param2);
}
// New object
Employee emp = new Employee(param1, param2);
Also constructor dont return anything so remove the void in your question.
Child class automatically gets access of all the public, protected members of the parent and child also has reference to parent class.
why you want to pass parent class reference to Child class. Instead you can call parent class constructor from child class like this:
public Child(){
super()
}
According to the question below, we can do this:
public class Child1 extends Super1 {
private int l;
public Child1(Super1 s){
super(s);
}
public Child1(){
this.l=20;
}
}
public class Super1 {
private int k;
public Super1(){
}
public Super1(Super1 s){
k=s.k;
}
}
i dont see your inheritance logic here correctly.
you have answer already..see below
class person()
class employee extends person(here)
hence you get to access its variables and methods..
just curious why you need to instantiate employee and injecting person class which is already parent to employee.
Your Employee will work as a person.You can call every method or variable (except private variables and methods) of Person by Employee object. But still if you want to pass a Person object to the constructor of Employee class then you can do it as fallows-
public Employee(Person person,.......){
super();//or pass required parameters according to constructor of Person class
//do whatever you want
}
it will work perfectly.
try this:
//if your Person constructor looks like this
public Person(param1, param2){
}
//then your copy constructor would look like this
public Employee(Person p){
super(p.getParam1 p.getParam2);
}

Inner class and this() constructor

I have 2 classes: Date and Person
Person has two attributes of Date class
Case 1
Date class is separate class from Person class. I have this piece of code working properly:
private String name;
private Date born;
private Date died; // null indicates still alive.
public Person(String initialName, int birthMonth, int birthDay,
int birthYear) {
// requirement from the instructor:
// **implement using the this() constructor**
this(initialName, new Date(birthMonth, birthDay, birthYear), null);
}
Case 2: Inner class (an assignment requirement)
I put the Date as the private inner class of Person
Now the above constructor code does not work anymore.
Here is the error message:
Description Resource Path Location Type
No enclosing instance of type Person is available due to some intermediate constructor invocation Person.java /Wk03_Ch10_FileIO_Ch13_Interfaces/wk03_Ch10_FileIO_Ch13_Inner_Classes line 43 Java Problem`
How do I solve the problem? I can do this:
Date dt = new Date(birthMonth, birthDay, birthYear);
Unfortunately this() has to be the first line in the constructor
Another work around is
public Person(String initialName, int birthMonth, int birthDay,
int birthYear) {
// implement using the this() constructor
this.name = initialName;
this.born = new Date(birthMonth, birthDay, birthYear);
this.died = null;
}
However the last piece of code does not satisfy my instructor requirement of using this() method inside the constructor.
You can't create inner member (non-static) classes within a call to another constructor. From JLS §8.8.7.1:
An explicit constructor invocation statement in a constructor body (sic: the call to this()) may not refer to any instance variables or instance methods or inner classes declared in this class or any superclass, or use this or super in any expression; otherwise, a compile-time error occurs.
The reason is that non-static inner classes may require access to the class while it's being constructed. For example:
public class OuterClass {
private String name;
private InnerClass inner;
public OuterClass(String name, InnerClass inner) {
this.name = name;
this.inner = inner;
}
public OuterClass(String name) {
this(name, new InnerClass()); // Will not compile
}
public class InnerClass {
public InnerClass() {
// Access to name is allowed since this inner class isn't static
System.out.println(name);
}
}
}
The major problem here is that when we construct the non-static inner class, it can access non-static members from its enclosing instance (the OuterClass, but the enclosing OuterClass hasn't yet made its call to super() and is therefore considered unsafe to access. In fact, if that code was allowed to compile, it would print null due to constructor invocation order. In short, the InnerClass would be created before the call to this.name = name, a similar concept to the information presented in this question.
The solution is to make InnerClass a static inner class and pass the name to it directly:
public class OuterClass {
private String name;
private InnerClass inner;
public OuterClass(String name, InnerClass inner) {
this.name = name;
this.inner = inner;
}
public OuterClass(String name) {
this(name, new InnerClass(name));
}
public static class InnerClass {
public InnerClass(String name) {
System.out.println(name);
}
}
}
InnerClass cannot access name from the OuterClass once it's declared static, so we have to pass it explicitly on construction now, but this is better since the initial code would have been broken anyway.
Edit:
Per your question:
What confused me is that I can create an object of a Date type in the Person's constructor, as long as it is not inside the this() method. I can do this: Date dt = new Date(birthMonth, birthDay, birthYear); What is the difference between the above and this(...., new Date(birthMonth, birthDay, birthYear), ...)?
The difference is that in the call outside of this(), all the calls to super() have taken place, they take place as part of this() because of implicit calls to super(), so the object has reached a point where it is considered okay to be accessed. Your Date instance can't access the Person class because there is no context for the Person and its fields yet, so the compiler doesn't allow it.
In short, once this() has been called, then at least the calls to super() have happened, which is the driving force behind this constraint, and also why overridable method calls are discouraged. If a method is overridden by a subclass and then called in the superclass' constructor, fields from the subclass can be accessed before the subclass has even been initialized, even resulting in null being returned for final fields. Basically, it's all about protecting yourself from accessing your class before a call to super() has been invoked.
While I would never create a Date class inside of a Person class (sounds like a bad idea from an application-modeling perspective!), you seem to have said that it is a requirement in some assignment.
If you are set up like this:
public class Person {
...
class Date {
...
}
}
Then inside methods of Person, you will need to invoke the Date constructor with:
this.new Date(...)
That is the syntax Java uses. You need an enclosing instance of type Person on which to create objects of the inner class. The thing about inner classes (whether they are member, local, or anonymous) is that each instance exists bound to an instance of the outer class. So if I had a person instance p, I could say:
p.new Date(...)
The big problem here though is that you cannot create dates in the Person constructor that use the about-to-be-created person! For example, this fails:
public Person() {
this(this.new Date());
}
because the value of this isn't ready for use in this way yet (although interestingly, you can sometimes use this inside constructors in other cases, such as storing it in arrays, for example).
Like you realized, making Date a static nested class is fine, because instances of static nested classes are not tied to any instances of the enclosing class, so this is the best solution. If you really have to have an inner class, you're not going to be able to pass a new date as an "argument" of a this() expression and have it bound to the person you are creating! Maybe that is the point of the assignment (is this a graduate class? :-))

Do subclasses inherit private fields?

This is an interview question.
Does subclasses inherit private
fields?
I answered "No", because we can't access them using the "normal OOP way". But the interviewer thinks that they are inherited, because we can access such fields indirectly or using reflection and they still exist in the object.
After I came back, I found the following quote in the javadoc:
Private Members in a Superclass
A
subclass does not inherit the private
members of its parent class.
Do you know any arguments for the interviewer's opinion?
Most of the confusion in the question/answers here surrounds the definition of Inheritance.
Obviously, as #DigitalRoss explains an OBJECT of a subclass must contain its superclass's private fields. As he states, having no access to a private member doesn't mean its not there.
However. This is different than the notion of inheritance for a class. As is the case in the java world, where there is a question of semantics the arbiter is the Java Language Specification (currently 3rd edition).
As the JLS states (https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2):
Members of a class that are declared
private are not inherited by
subclasses of that class. Only members
of a class that are declared protected
or public are inherited by subclasses
declared in a package other than the
one in which the class is declared.
This addresses the exact question posed by the interviewer: "do subCLASSES inherit private fields". (emphasis added by me)
The answer is No. They do not. OBJECTS of subclasses contain private fields of their superclasses. The subclass itself has NO NOTION of private fields of its superclass.
Is it semantics of a pedantic nature? Yes. Is it a useful interview question? Probably not. But the JLS establishes the definition for the Java world, and it does so (in this case) unambiguously.
EDITED (removed a parallel quote from Bjarne Stroustrup which due to the differences between java and c++ probably only add to the confusion. I'll let my answer rest on the JLS :)
Yes
It's important to realize that while there are two classes, there is only one object.
So, yes, of course it inherited the private fields. They are, presumably, essential for proper object functionality, and while an object of the parent class is not an object of the derived class, an instance of the derived class is mostly definitely an instance of the parent class. It could't very well be that without all of the fields.
No, you can't directly access them. Yes, they are inherited. They have to be.
It's a good question!
Update:
Err, "No"
Well, I guess we all learned something. Since the JLS originated the exact "not inherited" wording, it is correct to answer "no". Since the subclass can't access or modify the private fields, then, in other words, they are not inherited. But there really is just one object, it really does contain the private fields, and so if someone takes the JLS and tutorial wording the wrong way, it will be quite difficult to understand OOP, Java objects, and what is really happening.
Update to update:
The controversy here involves a fundamental ambiguity: what exactly is being discussed? The object? Or are we talking in some sense about the class itself? A lot of latitude is allowed when describing the class as opposed to the object. So the subclass does not inherit private fields, but an object that is an instance of the subclass certainly does contain the private fields.
No. Private fields are not inherited... and that's why Protected was invented. It is by design. I guess this justified the existence of protected modifier.
Now coming to the contexts. What you mean by inherited -- if it is there in the object created from derived class? yes, it is.
If you mean can it be useful to derived class. Well, no.
Now, when you come to functional programming the private field of super class is not inherited in a meaningful way for the subclass. For the subclass, a private field of super class is same as a private field of any other class.
Functionally, it's not inherited. But ideally, it is.
OK, just looked into Java tutorial they quote this:
Private Members in a Superclass
A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.
refer: http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html
I agree, that the field is there. But, subclass does not get any privilege on that private field. To a subclass, the private field is same as any private field of any other class.
I believe it's purely matter of point-of-view. You may mould the argument either side. It's better justify both way.
It depends on your definition of "inherit". Does the subclass still have the fields in memory? Definitely. Can it access them directly? No. It's just subtleties of the definition; the point is to understand what's really happening.
I will demonstrate the concept with code. Subclasses ACTUALLY inherit the private variables of super class. The only problem is that they are not accessible to the
child objects unless you provide public getters and setters for the private variables
in the super class.
Consider two class in package Dump. Child extends Parent.
If I remember correctly, a child object in memory consists of two regions. One is the parent part only and the other is the child part only. A child can access the private
section in the code of its parent only via a public method in the parent.
Think of it this way. Borat's father Boltok has a safe containing $100,000. He does not want to share his "private" variable safe. So, he does not provide a key for the safe. Borat inherits the safe. But, what good is it if he cannot even open it ? If only his
dad had provided the key.
Parent -
package Dump;
public class Parent {
private String reallyHidden;
private String notReallyHidden;
public String getNotReallyHidden() {
return notReallyHidden;
}
public void setNotReallyHidden(String notReallyHidden) {
this.notReallyHidden = notReallyHidden;
}
}//Parent
Child -
package Dump;
public class Child extends Parent {
private String childOnly;
public String getChildOnly() {
return childOnly;
}
public void setChildOnly(String childOnly) {
this.childOnly = childOnly;
}
public static void main(String [] args){
System.out.println("Testing...");
Child c1 = new Child();
c1.setChildOnly("childOnly");
c1.setNotReallyHidden("notReallyHidden");
//Attempting to access parent's reallyHidden
c1.reallyHidden;//Does not even compile
}//main
}//Child
No. They don't inherit it.
The fact some other class may use it indirectly says nothing about inheritance, but about encapsulation.
For instance:
class Some {
private int count;
public void increment() {
count++;
}
public String toString() {
return Integer.toString( count );
}
}
class UseIt {
void useIt() {
Some s = new Some();
s.increment();
s.increment();
s.increment();
int v = Integer.parseInt( s.toString() );
// hey, can you say you inherit it?
}
}
You can also get the value of count inside UseIt via reflection. It doesn't means, you inherit it.
UPDATE
Even though the value is there, it is not inherited by the subclass.
For instance a subclass defined as:
class SomeOther extends Some {
private int count = 1000;
#Override
public void increment() {
super.increment();
count *= 10000;
}
}
class UseIt {
public static void main( String ... args ) {
s = new SomeOther();
s.increment();
s.increment();
s.increment();
v = Integer.parseInt( s.toString() );
// what is the value of v?
}
}
This is exactly the same situation as the first example. The attribute count is hidden and not inherited by the subclass at all. Still, as DigitalRoss points out, the value is there, but not by means on inheritance.
Put it this way. If your father is wealthy and gives you a credit card, you can still buy thing with his money, but doesn't mean you have inherited all that money, does it?
Other update
It is very interesting though, to know why the attribute is there.
I frankly don't have the exact term to describe it, but it's the JVM and the way it works that loads also the "not inherited" parent definition.
We could actually change the parent and the subclass will still work.
For instance:
//A.java
class A {
private int i;
public String toString() { return ""+ i; }
}
// B.java
class B extends A {}
// Main.java
class Main {
public static void main( String [] args ) {
System.out.println( new B().toString() );
}
}
// Compile all the files
javac A.java B.java Main.java
// Run Main
java Main
// Outout is 0 as expected as B is using the A 'toString' definition
0
// Change A.java
class A {
public String toString() {
return "Nothing here";
}
}
// Recompile ONLY A.java
javac A.java
java Main
// B wasn't modified and yet it shows a different behaviour, this is not due to
// inheritance but the way Java loads the class
Output: Nothing here
I guess the exact term could be found here: The JavaTM Virtual Machine Specification
Well, my answer to interviewer's question is - Private members are not inherited in sub-classes but they are accessible to subclass or subclass's object only via public getter or setter methods or any such appropriate methods of original class. The normal practice is to keep the members private and access them using getter and setter methods which are public. So whats the point in only inheriting getter and setter methods when the private member they deal with are not available to the object? Here 'inherited' simply means it is available directly in the sub-class to play around by newly introduced methods in sub-class.
Save the below file as ParentClass.java and try it yourself ->
public class ParentClass {
private int x;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
}
class SubClass extends ParentClass {
private int y;
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void setXofParent(int x) {
setX(x);
}
}
class Main {
public static void main(String[] args) {
SubClass s = new SubClass();
s.setX(10);
s.setY(12);
System.out.println("X is :"+s.getX());
System.out.println("Y is :"+s.getY());
s.setXofParent(13);
System.out.println("Now X is :"+s.getX());
}
}
Output:
X is :10
Y is :12
Now X is :13
If we try to use private variable x of ParentClass in SubClass's method then it is not directly accessible for any modifications (means not inherited). But x can be modified in SubClass via setX() method of original class as done in setXofParent() method OR it can be modified using ChildClass object using setX() method or setXofParent() method which ultimately calls setX(). So here setX() and getX() are kind of gates to the private member x of a ParentClass.
Another simple example is Clock superclass has hours and mins as private members and appropriate getter and setter methods as public. Then comes DigitalClock as a sub-class of Clock. Here if the DigitalClock's object doesn't contain hours and mins members then things are screwed up.
Ok, this is a very interesting problem I researched a lot and came to a conclusion that private members of a superclass are indeed available (but not accessible) in the subclass's objects. To prove this, here is a sample code with a parent class and a child class and I am writing child class object to a txt file and reading a private member named 'bhavesh' in the file, hence proving it is indeed available in the child class but not accessible due to the access modifier.
import java.io.Serializable;
public class ParentClass implements Serializable {
public ParentClass() {
}
public int a=32131,b,c;
private int bhavesh=5555,rr,weq,refw;
}
import java.io.*;
import java.io.Serializable;
public class ChildClass extends ParentClass{
public ChildClass() {
super();
}
public static void main(String[] args) {
ChildClass childObj = new ChildClass();
ObjectOutputStream oos;
try {
oos = new ObjectOutputStream(new FileOutputStream("C:\\MyData1.txt"));
oos.writeObject(childObj); //Writing child class object and not parent class object
System.out.println("Writing complete !");
} catch (IOException e) {
}
}
}
Open MyData1.txt and search for the private member named 'bhavesh'. Please let me know what you guys think.
It would seem that a subclass does inherit the private fields in that these very fields are utilized in the inner workings of the subclass (philosophically speaking). A subclass, in its constructor, calls the superclass constructor. The superclass private fields are obviously inherited by the subclass calling the superclass constructor if the superclass constructor has initialized these fields in its constructor. That's just an example. But of course without accessor methods the subclass cannot access the superclass private fields (it's like not being able to pop the back panel of an iPhone to take the battery out to reset the phone... but the battery is still there).
PS
One of the many definitions of inheritance that I have come across:
"Inheritance -- a programming technique that allows a derived class to extend the functionality of a base class, inheriting all of its STATE (emphasis is mine) and behaviour."
The private fields, even if not accessible by the subclass, are the inherited state of the superclass.
For example,
class Person {
private String name;
public String getName () {
return this.name;
}
Person(String name) {
this.name = name;
}
}
public class Student extends Person {
Student(String name) {
super(name);
}
public String getStudentName() {
return this.getName(); // works
// "return this.name;" doesn't work, and the error is "The field Person.name is not visible"
}
}
public class Main {
public static void main(String[] args) {
Student s = new Student("Bill");
String name = s.getName(); // works
// "String name = s.name;" doesn't work, and the error is "The field Person.name is not visible"
System.out.println(name);
}
}
Padding bits/Alignment and the inclusion of Object Class in the VTABLE is not considered. So the object of the subclass does have a place for the private members of the Super class. However, it cannot be accessed from the subclass's objects...
I would have to answer that private fields in Java are inherited. Allow me to demonstrate:
public class Foo {
private int x; // This is the private field.
public Foo() {
x = 0; // Sets int x to 0.
}
//The following methods are declared "final" so that they can't be overridden.
public final void update() { x++; } // Increments x by 1.
public final int getX() { return x; } // Returns the x value.
}
public class Bar extends Foo {
public Bar() {
super(); // Because this extends a class with a constructor, it is required to run before anything else.
update(); //Runs the inherited update() method twice
update();
System.out.println(getX()); // Prints the inherited "x" int.
}
}
If you run in a program Bar bar = new Bar();, then you will always see the number "2" in the output box. Because the integer "x" is encapsulated with the methods update() and getX(), then it can be proven that the integer is inherited.
The confusion is that because you can't directly access the integer "x", then people argue that it isn't inherited. However, every non-static thing in a class, be it field or method, is inherited.
No, private fields are not inherited. The only reason is that subclass can not access them directly.
I believe, answer is totally dependent on the question, which has been asked. I mean, if question is
Can we directly access the private field of the super-class from
their sub-class ?
Then answer is No, if we go through the access specifier details, it is mentioned, private members are accessible only within the class itself.
But, if question is
Can we access the private field of the super-class from
their sub-class ?
Which means, it doesn't matters, what you will do to access the private member. In that case, we can make public method in the super-class and you can access the private member. So, in this case you are creating one interface/bridge to access the private member.
Other OOPs language like C++, have the friend function concept, by which we can access the private member of other class.
We can simply state that when a superclass is inherited, then the private members of superclass actually become private members of the subclass and cannot be further inherited or are inacessible to the objects of subclass.
A private class member or constructor is accessible only within the body of the top level class (§7.6) that encloses the declaration of the member or constructor. It is not inherited by subclasses. https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6
A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass
reference:
https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html#:~:text=Private%20Members%20in%20a%20Superclass,be%20used%20by%20the%20subclass.
I can try to help you.
When a subclass(named B, for example) extends a superclass (named A, for example), it automatically inherits fields (such as attributes and/or methods) from its superclass.
Now, B in its Memory Layout has the space for every field in class A even the private ones. The fact is that Java doesn't allow the subclass B to use the private fields because they are private.
As others have pointed out exerpt from JLS:
https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2:
Members of a class that are declared private are not inherited by
subclasses of that class. Only members of a class that are declared
protected or public are inherited by subclasses declared in a package
other than the one in which the class is declared.
The answer is NO without a doubt, without any iffs and buts. That revolves around the definition of inheritance. By definition inheritance is for classes, not for objects. Objects are created using class definitions. Inheritance is just another block to add to definition of a class. So, does a class inherits any private member of super class? NO
A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.
Private members (state and behavior) are inherited. They (can) affect the behavior and size of the object which is instantiated by the class. Not to mention that they are very well visible to the subclasses via all the encaptulation-breaking mechanisms that are available, or can be assumed by their implementers.
Although inheritance has a "defacto" definition, it definitely has no link to "visibility" aspects, which get assumed by the "no" answers.
So, there is no need to be diplomatic. JLS is just wrong at this point.
Any assumption that they are not "inherited" is unsafe and dangerous.
So among two defacto (partially) conflicting definitions (which I will not repeat), the only one that should be followed is the one that is safer (or safe).

Possible to change the outer class instance of an inner class in Java?

In Java, whenever an inner class instance is created, it is associated with an instance of an outer class. Out of curiosity, is it possible to associate the inner class with another instance of an outer class instead?
Yes, this is possible, although it sounds like a really bad idea to me. The idea is to set the otherwise final pointer to the outer instance using reflection (which is not guaranteed to succeed).
import java.lang.reflect.*;
public class Me {
final String name;
Me(String name) {
this.name = name;
}
class InnerMe {
String whoAreYou() {
return name;
}
}
InnerMe innerSelf() {
return new InnerMe();
}
public static void main(String args[]) throws Exception {
final Me me = new Me("Just the old me!");
final InnerMe innerMe = me.innerSelf();
System.out.println(innerMe.whoAreYou()); // "Just the old me!"
Field outerThis = innerMe.getClass().getDeclaredFields()[0];
outerThis.setAccessible(true);
outerThis.set(innerMe, new Me("New and improved me!"));
System.out.println(innerMe.whoAreYou()); // "New and improved me!"
}
}
The crucial part here is outerThis.setAccessible(true); -- a SecurityManager could enforce a policy that prohibits this from succeeding.
If you are speaking about instantiation time, it's possible using the following syntax:
public class Outer {
public class Inner {}
}
...
Outer o = new Outer();
Outer.Inner i = o.new Inner();
However, it's not possible (without setAccessible(true)) to associate the existing instance of inner class with the other instance of outer class, because the field pointing to the enclosing instance is final:
javap Outer$Inner
Compiled from "Outer.java"
public class Outer$Inner extends java.lang.Object{
final Outer this$0;
public Outer$Inner(Outer);
}
You should be able to, using reflection.
Just get all fields of the inner class (getClass().getDeclaredFields())and see which field holds the parent, then change it (using field.set(innerInstance, newParent). Before that you should make the field accessible - setAccessible(true))
Since the field appears to be final, you may take a look at this article to see how to circumvent that.
That said, you shouldn't need to do this at all - it would be a double ugly hack for no actual gain.

Categories

Resources