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.
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.
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
How do you create an inner class object with reflection? Both Inner and Outer classes have default constructors that take no parameters
Outer class {
Inner class{
}
public void createO() {
Outer.Inner ob = new Inner ();//that works
Inner.class.newInstance(); //<--why does this not compile?
}
}
"If the constructor's declaring class is an inner class in a non-static context, the first argument to the constructor needs to be the enclosing instance; see section 15.9.3 of The Java™ Language Specification."
That means you can never construct an inner class using Class.newInstance; instead, you must use the constructor that takes a single Outer instance. Here's some example code that demonstrates its use:
class Outer {
class Inner {
#Override
public String toString() {
return String.format("#<Inner[%h] outer=%s>", this, Outer.this);
}
}
#Override
public String toString() {
return String.format("#<Outer[%h]>", this);
}
public Inner newInner() {
return new Inner();
}
public Inner newInnerReflect() throws Exception {
return Inner.class.getDeclaredConstructor(Outer.class).newInstance(this);
}
public static void main(String[] args) throws Exception {
Outer outer = new Outer();
System.out.println(outer);
System.out.println(outer.newInner());
System.out.println(outer.newInnerReflect());
System.out.println(outer.new Inner());
System.out.println(Inner.class.getDeclaredConstructor(Outer.class).newInstance(outer));
}
}
(Note that in standard Java terminology, an inner class is always non-static. A static member class is called a nested class.)
Oracle documentation(in below link) says that:
Non-static nested classes (inner classes) have access to other members
of the enclosing class, even if they are declared private.
But in below example I created an object objin (of inner class) and it couldn't access any of the method or variable of its enclosing outer class. Below is the code, could you any one clarify on the same?
http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
package Package_1;
public class Outer {
int k;
public void Multiply()
{
System.out.println("inside outer class' method multiply");
}
public class Inner {
int l;
public void Division()
{
System.out.println("inside inner class' method Divison");
}
}
}
Class with Main method
package Package_1;
public class D {
public static void main(String[] args) {
Outer objout = new Outer();
objout.k = 5;
objout.Multiply();
Outer.Inner objin = objout.new Inner();
objin.l = 7;
objin.Division();
}
}
With objin object I couldn't access that Multiple method in its enclosing class.
I see your "privates"!
From the code of the non-static nested class (inner class) you have access to both public and private members of the enclosing class.
But it's your "privates", not mine!
This is what you're thinking when you try do objin.Multiply(): you are accessing Multiply() as though it's a member of the inner class, but it's not. Remember, you can see it from within the code of the inner class, but it will not be exposed as though it's yours.
This is what the specification says
public class Outer{
private int x;
private void method(){
}
public void publicMethod(){}
public class Inner{
//has access to even private properties of x
method(); //can be called
//NOTE: Only has ACCESS and does not INHERIT those methods
}
}
What you are trying is to access the publicMethod() with the instance of Inner, which does not have any method of that name.
THE CRUX:
The non-static nested classes just has the access to all properties and methods of container class, but does not inherit those methods.
objin.Multiply() cannot work as the crux explains that Multiply() is defined on Outer and not Inner, so there is no method Multiply() on Inner
The documentation doesn't say that you can access to fields and methods of the outer class by using a reference to the inner class. So you can't do
objin.Multiply();
because Multiply is not a method of Inner. What you can do is:
public class Inner {
int l;
public void Division()
{
System.out.println("I can access the field k in outer: " + k);
System.out.println("I can access the method Multiply in outer (even if Multiply was private): ");
Multiply();
// which is a shortcut for
Outer.this.Multiply();
}
}
PS: please respect the Java naming conventions. Methods start with a lowercase letter.
You are trying to access the method by using instance of the Inner class object. It can be accessed outside only by Outer class method. You can call the method inside the class definition of the Inner class directly but not by using the instance of inner class. if you still want to do this try :
package Package_1;
public class Outer {
int k;
public void Multiply()
{
System.out.println("inside outer class' method multiply");
}
public class Inner {
int l;
public void Division()
{
System.out.println("inside inner class' method Divison");
}
public void Multiply() {
Outer.this.Multiply(); //Outer class method.
}
}
}