2

Consider the following code

class A{}
class B{
    void main(){
        A a1=new A();
        class A{}
        A a2=new A();
        System.out.println(a1); // A@___
        System.out.println(a2); // B$1A@____
    }
}

The class A and class B are not inside any package, How can I create the object of the outer class A inside main() after the method local inner class is created. In other words, how can I create the "a2" object, an object of outer class A?

I checked this by putting these classes in a Package, and I was able to create the object of outer class A using the fully qualified name. But, could not find a way to do the same when they are not inside any package.

Nikunj Gupta
  • 126
  • 2
  • 8
  • If you want to create an object of `A` inside `B` then remove `class A{}` from your B. Why you need that? – Jainik Feb 20 '19 at 07:39
  • there is no need, but I was curious how an object of 'A' be created if class A{} was also in class B. – Nikunj Gupta Feb 20 '19 at 07:42
  • I see what you mean, you need to use fully qualified name for outer class. See an answer below – Jainik Feb 20 '19 at 07:46

3 Answers3

4

You can use Class.forName() to load the class you would like to instantiate:

class A {}

class B {
     public static void main(String[] args) throws Exception {
         A a1 = new A();
         class A {}
         A a2 = new A();
         Class<?> clazz = Class.forName("A");
         Object a3 = clazz.getDeclaredConstructor().newInstance();

         System.out.println(a1); // A@___
         System.out.println(a2); // B$1A@____  
         System.out.println(a3); // A@___
     }
}

This works, as the local class A in B.main() has a different fully qualified domain name as the one declared on the same level as B:

System.out.println(a1.getClass()); // class A
System.out.println(a2.getClass()); // class B$1A
System.out.println(a3.getClass()); // class A

I've had to use Object as the type of a3 because there is no way to reference the outer A inside main() once the local class A has been declared.

Lino
  • 19,604
  • 6
  • 47
  • 65
3

With no package for both A classes you don't have any way to distinguish them.
As the A type is referred, the compiler will refer to the most local/close A class declaration :

A a1=new A(); // refer the outer (the single that is visible in this scope)
class A{}
A a2=new A(); // refer the inner : the closest in this scope

Note that the default package is not recommended but using it with the same class name is really a thing not to do.

Edit

With a Supplier declared before the local A class, you could create the outer A object after the local class declaration since Supplier creates the object only when get() is invoked :

A a1=new A();
Supplier<A> Asupplier = A::new;
class A{}
System.out.println(a1); // A@___
System.out.println(Asupplier.get()); // A@_____
davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • 1
    Does this mean that the method local inner class having the same name as the outer class hide the outer class when they are in default package? – Nikunj Gupta Feb 20 '19 at 07:50
  • 2
    I don't know if "hiding" is the correct term but without canonical name (package + class name) how do you want to distinguish `A` from `A` when you refer them ? – davidxxx Feb 20 '19 at 07:56
0

If you are using the same name of inner class like outer class then you need to use fully qualified class name to refer an outer class.

This is like the same concept applies to method or variables where local declaration gets higher priority.

As a general rule of thumb, using same class names are not recommended and more confusing

Reference link to read about this: https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.4.2

An excellent SO answer on something similar can be found here. Inner Class visibility SO Thread

Jainik
  • 2,352
  • 1
  • 19
  • 27