I have read this concept in respect to static inner class : ViewHolder declared as inner class inside the adapter of ListView to enhance the performance of getView().
Consider the below class
public class OuterClass{
public class InnerClass{
private int privateProperty= -2;
}
public static void main(String[] args) {
OuterClass oc = new OuterClass();
InnerClass ic = oc.new InnerClass();
ic.privateProperty = -98;
}
}
If inner class contains private properties and an object of inner class is created inside a method of outer class then the inner class private properties can be accessed directly using . 'dot' operator.
I have read somewhere that the private properties of the inner class are accessed using synthetic setter getter methods from outer class
I want to clear my concept regarding the same.
The compiler generates method to access private members of an inner class. If you compile your example code and examine the bytecode, you will find that it is as if it were written like this:
public class OuterClass{
public class InnerClass{
private int privateProperty= -2;
static int access$002(InnerClass obj, int value) {
obj.privateProperty = value;
return value;
}
}
public static void main(String[] args) {
OuterClass oc = new OuterClass();
InnerClass ic = oc.new InnerClass();
InnerClass.access$002(ic, -98);
}
}
This conversion of the line
ic.privateProperty = -98;
into the method call:
InnerClass.access$002(ic, -98);
together with the creation of the static method InnerClass.access$002 is done by the compiler. The static method (named access$002 by my compiler) is an example of a "synthetic setter method" you have read about. As a result, the bytecode for the two classes do not violate Java's access rules.
Your concept is wrong.. Inner classes are meant to use inside the container classes only, This idea coming from the concept that you don't want to expose unnecessery classes to the developer, Which is not relevant to all of the project.
In this case InnerClass will be related to only to OuterClass. In the main you should create new only to OuterClasS and the OuterClass will create instance of InnerClass
So it should be something like this:
public class OuterClass{
private InnerClass in;
public Class OuterClass() {
in = new InnerClass();
}
//getters & setters
public void setInnerProperty(int x) {
in.setPrivateProperty(x);
}
public class InnerClass{
private int privateProperty= -2;
//getters & setters
}
public static void main(String[] args) {
OuterClass oc = new OuterClass();
oc.setInnerProperty(98);
}
}
In case you want to change it from the main.. This is the way to do it, but not recomended.
Hope that helps
Related
I'm studying inner classes in java. I have seen that if inner class is non static then it can easily access the outer class variable. But what if inner class is static, then how can we take a access of outer class's variable using static's class object ?
Below is my code, where am accessing outer class variable from inner class
package org;
public class Outerclass {
String name = "Europe";
public String getname() {
return name;
}
public void setname(String name) {
this.name = name;
System.out.println(this.name);
}
static class innerclass {
void updatename() {
Outerclass o = new Outerclass();
o.setname("USA");
}
}
public static void main(String[] args) {
Outerclass b = new Outerclass();
b.name; // why this error here ? "Syntax error, insert "VariableDeclarators" to complete LocalVariableDeclaration"
innerclass i = new innerclass();
i.updatename();
}
}
You can't access non-static contents inside the static content
When we create static inner class by default it will created as a outer template as a association of inner template. So we can load both together but only static things can be inside the static inner class.
Now there are no connection between objects of the classes. But there are connection between the templates.
Following is your code I have done some modification might help you
public class Demo {
String name = "Europe";
public String getname() {
return name;
}
public void setname(String name) {
this.name = name;
System.out.println(this.name);
}
static class innerclass {
void updatename() {
Demo o = new Demo();
o.setname("USA");
}
}
public static void main(String[] args) {
Demo b = new Demo();
String a = b.name; // why this error here ? "Syntax error, insert "VariableDeclarators" to complete LocalVariableDeclaration"
System.out.println(a);
innerclass i = new innerclass();
i.updatename();
}
}
Inner static class behives same as normal class:
can access static property/method of outer class
can't non-access static / methods of outre class directly, they will require an outerclass instance reference to do so.
it does not rquire an instance of outer class to be created
It is used mostly in two scenarios:
you are creating a group of classes with similar nature/function, and you want to keep them under one 'Napespace'
you want to create a private class that will not be visible to anyone, except to outter class (private static inner class). That way you can create interface implementations visible only to your outer class.
Non-static inner class:
it requires instance of outer class to be created
it can access methods and properties of outer class.
Quote:
...inner classes can access all members of the declaring class, even
private members. In fact, the inner class itself is said to be a
member of the class; therefore, following the rules of object-oriented
engineering, it should have access to all members of the class.
I read that an instance of an inner class cannot be created without an instance of outer class. But when I tried to create an instance of my inner class using it as an instance member of my outer class, it worked.
I understand that it is creating an inner object through a reference to my outer class object, but is it the right way to do it?
Below is my code snippet:
public class TestInner {
private Nonstatic non = null;
private static int access = 4;
public class Nonstatic {
void hello() {
access = 90;
}
}
public static void main(String[] args) {
TestInner outer = new TestInner();
TestInner.Nonstatic innern= outer.new Nonstatic();
System.out.println("Non static obj1 is "+innern);
outer.testinnerObj();
}
public void testinnerObj() {
non = new Nonstatic();
System.out.println("Non static obj2 is "+non);
non.hello();
}
}
You're writing "An instance of Inner class cannot be created without an instance of outer class". And that's exactly what you are doing.
First, you create an instance of the "outer" class:
TestInner outer = new TestInner();
Then, you create an instance of the "inner" class - it only lives
in the scope of outer:
TestInner.Nonstatic innern= outer.new Nonstatic();
So, the question maybe boils down to this: yes, you are creating the object in the static main method. But that does not matter, because you are using the syntax outer.newwhich creates it in the scope of outer.
Hope that helps.
Inner classes can even access the private variables/methods of outer classes. Then why I am getting compiler error when I am trying to access the private method of outer class object from inner class object in my code.
public class OuterClass {
private int id=5;
private void printSomeText()
{
System.out.println("Text is ");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
OuterClass outer = new OuterClass();
outer.printSomeText();
OuterClass.InnerClass inner = outer.new InnerClass();
inner.printSomeText();// gives compiler error
}
class InnerClass{
public void printText() {
System.out.println("Some Text");
}
}
}
Inner classes can even access the private variables/methods of outer classes.
Yes, which means that in your InnerClass::printText method, you can call:
OuterClass.this.printSomeText(); //private method is accessible
However to be able to write inner.printSomeText();, InnerClass would need its own printSomeText method, either declared in the class itself or inherited from a parent class.
I have a nested (static) class with a private field and a setter method for this field.
public class Outer{
private static class Inner{ // List node
private String fieldA;
// ...other members...
public void setA(String fieldA)
{
//.. do importent stuff before setting fieldA
this.fieldA = fieldA;
}
}
}
Now we had a bug because the fieldA is accessed directly (and not by setter method setA) by Outer class although the field fieldA is private. How can I enforce developers to use the setter method instead of directly accessing the field?
I have read the related topic Access modifiers inside a private static nested class in Java that states that it is by design. But is there a workaround to ensure using setter method by outer class?
If the class must not be moved to outside of Outer, you should define an interface for Inner and use only that. If you have only few instances and this is not a performance critical point of your application, you could just create anonymous implementations of that interface. The class isn't static anymore but at least it's a short and readable solution.
private static interface Inner {
void setA(String a);
}
private static Inner createInner() {
return new Inner() {
private String a;
#Override
public void setA(String a) {
this.a = a;
}
};
}
If you want to keep the class static, I don't see many options to hide anything from the outer class. You can try to make it more obvious that the inner class should be used carefully.
It looks a bit strange, but you could move the implementation into the interface like in the following example - that doesn't really prevent anyone from using Inner.InnerImpl, but it should imply that the class InnerImpl belongs to Inner and is not be used directly.
public class Outer{
private static interface Inner {
static class InnerImpl implements Inner {
private String a;
#Override
public void setA(String a) {
this.a = a;
}
}
void setA(String a);
}
// either instantiate directly or again wrap it in a `createInner()` method
// Inner inner = new Inner.InnerImpl();
}
Actually here is another quite simple option. I think for this special case you could justify introducing a new naming convention to avoid accidental use of properties.
private static class Inner {
private String _a;
public void setA(String a) {
this._a = a;
}
}
Here is the code where I am updating the instance variable x of OuterClass by static variable of StaticInner. I understand that the static inner classes cannot refer directly to instance variable of outer classes. I am using an instance of outerclass to refer to its instance variable 'x' and update it. This goes into stackoverflow error. The code complies fine. The last line in the code does not compile which I commented out. I don't understand what the problem with that line.
public class OuterClass {
private int x = 10;
private static int y = 15;
private static StaticInner si=null;
public OuterClass() {
setStaticInner();
this.x=si.ic.x;
}
public static class StaticInner {
private static int z = 20;
private OuterClass ic = new OuterClass();
public void increment() {
OuterClass.y+=z;
z+=OuterClass.y;
ic.x+=10;
}
}
public void setStaticInner(){
si=new StaticInner();
}
public static void main(String[] args){
OuterClass ic = new OuterClass();
ic.si.increment();
System.out.println(ic.x);
//OuterClass.StaticInner sb1 = ic.new StaticInner(); This line does not compile.
}
}
You have a circular dependency in the constructors, resulting in a recursive call between them
Outer(){
createInner()
}
Inner(){
createOuter()
}
This won't work (unless you use reflection, but that defeats the purpose).
You need to structure the classes so there is a linear dependency. I recommend passing the outer instance to the inner constructor
Outer(){
inner = new Inner(this);
}
Inner(Outer o){
myouter = o;
}
Don't qualify "new" with an outer class instance. That only applies to inner classes. Just instantiate the nested class like any other.
You should not need to mention the outer class at all when working with a static nested class inside the outer class.