When we define inner classes, I understand that static inner classes are accessed with the outer class and inner member class exist with the instance of the outer class.
The confusion is, if I want to hold an instance of an non-private inner member class, then the variable declaration goes like:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
How outer class is able to reference the inner member class like this? What is happening here?
Sample Code:
public class NestedClasses {
public static void main(String[] args) {
A.B b = new A().new B(); // <- How A is directly accessing B, B is not defined as static.
A.StaticClass staticClass = new A.StaticClass();
}
}
class A {
static int x;
int y;
A() {
System.out.println(this.getClass().getName());
}
static class StaticClass {
StaticClass() {
System.out.println(this.getClass().getName());
}
}
class B {
B() {
System.out.println(this.getClass().getName());
}
}
}
Related
I was wondering if there is any way to create a method-local inner class object in main() method with the help of Outerclass object.
public class Outerclass {
// instance method of the outer class
void my_Method() {
int num = 23;
// method-local inner class
class MethodInner_Demo {
public void print() {
System.out.println("This is method inner class "+num);
}
} // end of inner class
// Accessing the inner class
MethodInner_Demo inner = new MethodInner_Demo();
inner.print();
}
public static void main(String args[]) {
Outerclass outer = new Outerclass();
outer.my_Method();
}
}
Edit-1:
I was exploring the way to instantiate a method-local inner class in the main method ( I know the method-local inner class is not visible to the main method) but still, is there any workaround?
public class Outerclass {
// instance method of the outer class
void my_Method() {
int num = 23;
// method-local inner class
class MethodInner_Demo {
public void print() {
System.out.println("This is method inner class "+num);
}
} // end of inner class
}
public static void main(String args[]) {
Outerclass outer = new Outerclass();
//inner-class object is created while calling my_Method()
// TBH IDK how to do this
outer.my_Method().new MethodInner_Demo();
}
}
Class MethodInner_Demo is a local class, not an inner class, since it is declared in the body of a method. See e.g. The Java™ Tutorials.
A local class can only be seen by code in the method where is it declared.
If you want to be able to create an instance of the class from another method, then you need to move the class outside the method, so it becomes an actual inner class.
You can then create an instance, assuming you're "authorized", as defined by the public, protected, and private access modifiers. You do that by qualifying the new operator with an instance of the outer class.
In your case, we also need to add a field to carry the value of num.
public class Outerclass {
// instance method of the outer class
void my_Method() {
int num = 23;
// Accessing the inner class
Inner_Demo inner = new Inner_Demo(num);
inner.print();
}
// inner class
class Inner_Demo {
private final int num;
Inner_Demo(int num) {
this.num = num;
}
public void print() {
System.out.println("This is inner class "+num);
}
} // end of inner class
public static void main(String args[]) {
Outerclass outer = new Outerclass();
outer.my_Method();
// Accessing the inner class
int num = 42;
Inner_Demo inner = outer.new Inner_Demo(num);
inner.print();
}
}
The type of the method local class is invisible to main. However, you can create that instance and pass it to main.
public class OuterClass {
Object createInnerClass() {
int num = 23;
class InnerClass {
#Override
public String toString() {
return "I'm InnerClass. num=" + num;
}
}
return new InnerClass();
}
public static void main(String args[]) {
OuterClass outer = new OuterClass();
Object obj = outer.createInnerClass();
System.out.println(obj);
}
}
output:
I'm InnerClass. num=23
I can understand why inner class can access outer class private members, but its not clear why instance of inner class defined in outer class method can access inner class private members. For example: the following code works fine.
class OuterClass
{
int outer_default;
private int outer_private;
protected int outer_protected;
static int outer_static;
static {
outer_static=5;
}
public OuterClass()
{
outer_default=1;
outer_private=2;
outer_protected=3;
System.out.println("Outerclass object created!!!!");
}
public void outerMethod()
{
System.out.println("**********Outerclass accessing outer class members********************");
System.out.println("outerdefault: "+outer_default);
System.out.println("outerprivate: "+outer_private);
System.out.println("outerprotected: "+outer_protected);
System.out.println("outerstatic: "+outer_static);
System.out.println("**************************************************************");
InnerClass innerObj = new InnerClass();
System.out.println("**********Outerclass accessing inner class members********************");
System.out.println("innerdefault: "+innerObj.inner_default);
System.out.println("innerprivate: "+innerObj.inner_private); //HOW IS THIS POSSIBLE??????
System.out.println("innerprotected: "+innerObj.inner_protected);
System.out.println("**************************************************************");
}
class InnerClass
{
int inner_default;
private int inner_private;
protected int inner_protected;
public InnerClass()
{
inner_default=4;
inner_private=5;
inner_protected=3;
System.out.println("Innerclass object created!!!!");
}
public void innerMethod()
{
System.out.println("**********Innerclass accessing inner class members********************");
System.out.println("innerdefault: "+inner_default);
System.out.println("innerprivate: "+inner_private);
System.out.println("innerprotected: "+inner_protected);
System.out.println("**************************************************************");
System.out.println("**********Innerclass accessing outer class members********************");
System.out.println("outerdefault: "+outer_default);
System.out.println("outerprivate: "+outer_private);
System.out.println("outerprotected: "+outer_protected);
System.out.println("outerstatic: "+outer_static);
System.out.println("**************************************************************");
}
}
}
class Main {
public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.outerMethod();
OuterClass.InnerClass inner = outer.new InnerClass();
inner.innerMethod();
}
}
I have commented near the code in which I have doubt.
class Outer
{
int x=10;
class Inner
{
void show()
{
System.out.println(x);
}
}
public static void main(String args[])
{
Outer obj=new Outer();
Inner obj1=new Outer().new Inner();
obj1.show();
}
}
I tried making a non static nested class and tried to use non static data member of outer class in non static inner class. I did not get that if x is non static, how i am using it without object. Kindly give me the answer?
You're not using it without an object. Inner (non-static nested) classes have a reference to the outer object, whose x is used.
Inner class is just a syntactic sugar to have an implicit reference to an outer class. Internally (after javac compilation) your class Inner looks like this:
static class Inner
{
private final Outer this$0;
public Inner(Outer outer) {
this$0 = outer;
}
void show()
{
System.out.println(this$0.x);
}
}
And when you write Inner obj1=new Outer().new Inner(); the compiler changes it to something like Inner obj1=new Inner(new Outer());.
I have a following code
class OuterClass<T>{
class Innerclass{
int k;
}
public static void main(String argv[]){
OuterClass<Integer> out =new OuterClass<>();
Innerclass in; // errors out
}
}
But for a class with no generics like the following code, I could create object for inner class.
class OuterClass{
class Innerclass{
int k;
}
public static void main(String argv[]){
OuterClass out =new OuterClass();
Innerclass in; // No error
}
}
why am i not able to create object of inner class though no generics are used in the inner class in my first example? Please explain.
Your main method belongs to OuterClass and is static in there. Since InnerClass is not a static class but implicitly depends on the generic type T (the generic type is available in the inner class, even if your example isn't using it), you cannot reference it from a static method.
In other words, since InnerClass depends on the generic type, you cannot break it "lose" from OuterClass and use it outside of it.
If your inner class won't depend on the generic type, you can just make it static. However, you might want to consider just extracting it into a separate class rather than nesting classes in this case:
class OuterClass<T> {
static class InnerClass {
int k;
}
public static void main( String argv[] ) {
InnerClass inner = new InnerClass();
}
}
If the generic is important for the inner class, you can tell the compiler which generic to infer for the outer class by specifying it (note that the generic type of outer and inner must match) or by using OuterClass.InnerClass in which case the compiler will use the raw type:
class OuterClass<T> {
class InnerClass {
int k;
}
public static void main( String argv[] ) {
OuterClass<String> outer = new OuterClass<String>();
// works and has the "correct" generic type
OuterClass<String>.InnerClass inner1 = outer.new InnerClass();
// works, but uses the raw type
OuterClass.InnerClass inner2 = outer.new InnerClass();
}
}
Note that you need an enclosing instance outer of type OuterClass<T> in order to instantiate InnerClass (since the class is not static, it belongs to an instance of OuterClass).
This also goes for the example without generics: you will need an enclosing instance to instantiate the inner class, so
class OuterClass {
class InnerClass {
int k;
}
public static void main( String argv[] ) {
OuterClass outer = new OuterClass();
InnerClass in = outer.new InnerClass();
}
}
will work while
class OuterClass {
class InnerClass {
int k;
}
public static void main( String argv[] ) {
OuterClass outer = new OuterClass();
InnerClass in = new InnerClass();
}
}
won't.
I am wondering if the following is valid in Java:
class OuterClass {
OuterClass(param1, param2) {
...some initialization code...
}
void do {
// Here is where the doubt lays
OuterClass.InnerClass ic = this.new InnerClass();
}
class InnerClass {
}
}
Basically what I am trying to achieve here is to instantiate an inner class object from the current instance of the outer class, not a new instance, the current one. I believe this comes handy is when the constructor of the outer class is not empty (takes parameters) and we don't know what pass to them (they can't be null since some might be assigned to a class variable that is accessed by the inner class object).
Let me know if I explained myself well.
Thanks in advance!
Regarding:
public class OuterClass {
OuterClass() {
// ...some initialization code...
}
void doSomething() {
OuterClass.InnerClass ic = this.new InnerClass();
}
class InnerClass {
}
You don't need the explicit OuterClass identifier nor the this as they're implied.
So this is unnecessary:
OuterClass.InnerClass ic = this.new InnerClass();
And this is fine inside of an instance method:
InnerClass ic = new InnerClass();
Things get dicier though if you're creating an object of InnerClass in a static method such as main that is held inside of OuterClass. There you'll need to be more explicit:
This won't work
public class OuterClass {
public static void main(String[] args) {
InnerClass otherInnerVar = new InnerClass(); // won't work
}
But this will work fine:
public class OuterClass {
public static void main(String[] args) {
InnerClass otherInnerVar2 = new OuterClass().new InnerClass(); // will work
}
Every instance of an inner class, unless the Class is declared as static, must have a 'connected' instance of an outer class, in order to be instantiated.
This won't work:
public class Outer {
public class Inner {
}
public static void main(String[] args) {
Inner inner = new Inner(); //compilation error
}
}
However, this will work, it doesn't need an instance of Outer, since the static keyword is used:
public class Outer {
public static class Inner {
}
public static void main(String[] args) {
Inner inner = new Inner();
}
}
more info: java inner classes
Above is the example for creating Inner class object inside outer class and outside outer class:
public class OuterClass {
public class InnerClass{
public void myMethod(){
System.out.println("inside inner class");
}
}
public void myMethod(){
System.out.println("outer class method");
InnerClass class1 = new InnerClass();
class1.myMethod();
}
public static void main(String[] args){
//OuterClass.InnerClass class1 = new OuterClass().i
OuterClass outerClassObj = new OuterClass();
OuterClass.InnerClass innerClassObj = outerClassObj.new InnerClass();
innerClassObj.myMethod();
}
}