Внутренний класс Java с тем же именем, что и другой класс верхнего уровня

У меня есть вопрос, связанный с внутренними классами Java.

Есть ли способ получить доступ к классу верхнего уровня A из класса высшего уровня Main, который определяет внутренний класс A?

Ниже приведен пример кода, демонстрирующий проблему:

class A {   // Outer Class A
  { 
    System.out.println("A outer");
  }
}

class B {   // Outer Class B
  { 
    System.out.println("B outer"); 
  }
}

public class Main { 
  class A {  // Inner Class A
    {
      System.out.println("A inner");
    }
  }

  public void newA() {      
    class A {   // Local Class A
      { 
        System.out.println("A local");
      }
    }
    new A();
  }

  public static void main(String[] args) {
    new Main().newA();  // prints "A local"
    new Main().new A(); // prints "A inner"
    //new A();    // compiler error: No enclosing instance of type Main is Accessible.
    new B();      // but this works and prints "B outer" 
  }
}

6 ответов

Решение

Используйте полное имя класса:

new com.mypackage.A();

Вы должны предоставить разные имена пакетов для ваших двух AЕсли они явно разных типов, вы можете ссылаться на них по их полным именам.

Например:

my.package.for.toplevel.A outerA = new my.package.for.toplevel.A(); // prints "A outer"
                                                                    // if this is the
                                                                    // package

Или, что еще лучше, используйте два разных имени для двух разных классов.

Если ваши классы находятся в пакетах, я ожидаю, что это будет самый простой способ достижения этого. Я не верю, что есть какой-либо эквивалент C# global:: для Java, чтобы заставить такого рода вещи.

В конечном счете, я бы просто попытался изменить имена классов, чтобы избежать проблемы, возникающей в первую очередь. Обычно это лучший подход, чем использование обходных путей.

Говорят, что имя внутреннего класса скрывает имя класса верхнего уровня. На класс верхнего уровня нельзя ссылаться по его простому имени в области видимости внутреннего класса; на класс верхнего уровня можно ссылаться только через определенное имя.

Если класс верхнего уровня находится в пакете по умолчанию (в этом случае его каноническое имя совпадает с его простым именем), вы все равно можете получить к нему доступ через отражение.

Да, просто используйте пакеты или избегайте называть их одинаковыми с самого начала. Интересно, какова ваша причина, чтобы назвать их так или иначе?

Чтобы объяснить вашу ошибку, это происходит из-за того, что он пытается получить доступ к внутреннему A, но так как этот класс не объявлен как статический и нет доступного экземпляра Main, он не может создать нестатический внутренний A, который требует ссылки в родительский главный экземпляр.

Предполагается, что классы находятся в пакете по умолчанию. Для разрешения конфликта именования в этом случае необходимо либо переименовать конфликтующие классы, либо использовать именованный пакет. Затем используйте FQCN для решения проблемы.

Другие вопросы по тегам