Как обращаться к классу, когда сталкиваются как простые, так и полностью определенные имена - PullRequest
0 голосов
/ 01 июня 2018

Рассмотрим следующий патологический пример:

class Ideone {
  static class ArrayList<T> {
    ArrayList() {
      System.out.println("!!");
    }
  }

  static class java {
    static class util {
      static class ArrayList<T> {
        ArrayList() {
          System.out.println("Here");
        }
      }
    }
  }

  public static void main(String[] args) {
    new ArrayList<>();
    new java.util.ArrayList<>();
    // Can I refer to the "usual" java.util.ArrayList?
  }
}

Два экземпляра, созданные в конструкторе, являются вложенными классами.

Но как я могу сослаться на java.util.ArrayList что мы все знаем и любим в одном классе?Мы не можем импортировать его и не можем использовать полное имя, так как вместо него будут использоваться вложенные символы классов.

Что мы можем сделать в этом случае?(Кроме очевидного - перестаньте использовать такие бессмысленные злые имена для вложенных классов).

Ответы [ 4 ]

0 голосов
/ 01 июня 2018

Вы больше не можете напрямую ссылаться на java.util.ArrayList, если вы сделали 2 вещи, которые вы сделали:

  1. Скрыть простое имя ArrayList со статическим вложенным классом в области видимости.
  2. Скрыть полностью определенное имя java.util.ArrayList с классом ArrayList, вложенным в класс util, вложенным во вложенный класс java.

Вы даже не можете "разбить"«импорт в попытке использовать« частично квалифицированный »импорт.

import java.*;

...

// This doesn't work!
new util.ArrayList<>();

Вы можете import java.*;, но это бесполезно;классы java не определены напрямую.

Однако вы можете косвенно ссылаться на класс java.util.ArrayList, поскольку он не final.Вне области действия класса Ideone объявите подкласс с другим именем.

class AnArrayList<T> extends java.util.ArrayList<T> {}

Затем вы можете обратиться к этому классу и программе к интерфейсу:

List<Integer> al = new AnArrayList<>();  // won't print !! or Here
0 голосов
/ 01 июня 2018

Я собираюсь выйти на конечность и сказать, что на нее нельзя ссылаться из Ideone.Единственное решение, которое я вижу, - это создать другой класс Idetwo (который является вложенным элементом Ideone (т.е. он находится в том же файле)) и вернуть оттуда java.util.ArrayList для использования в Ideone:

import java.util.ArrayList;

class Ideone {
    ...
}

class Idetwo {
    static ArrayList<Integer> getList() {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        return list;
    }
}

И вы просто изменили бы основной метод Ideone на что-то вроде:

public static void main(String[] args) throws Exception {
    new Ideone.ArrayList<>();
    new Ideone.java.util.ArrayList<>();
    Idetwo.getList().forEach(System.out::println);
}

Вывод:

!!
Here
1
2
3

Примечание : с этим методом импорт java.util.ArrayList будет работать нормально.Однако если вы вызываете List<Integer> list = Idetwo.getList(); внутри основного метода Ideone, вам необходимо импортировать java.util.*, так как отдельный импорт не будет работать (интересно).

0 голосов
/ 01 июня 2018

Именно поэтому пакеты начинаются с строчных букв, а типы - с прописных, поскольку - самая первая редакция официальных соглашений о коде для java .Я не думаю, что когда-либо видел, как java-код нарушал это соглашение.

Но вы можете ссылаться на внутренний тип извне, используя его полное имя:

com.whatever.bad.project.SomeClass.java.util.ArrayList

Когда у вас естьчтобы ссылаться на внешний тип изнутри, вы, вероятно, можете изменить этот исходный файл, чтобы он соответствовал правилам именования Java.

0 голосов
/ 01 июня 2018

Вы пробовали

Class cls = ClassLoader.getSystemClassLoader().loadClass("java.util.ArrayList");
List arrayList = cls.newInstance();

Прошло много времени с тех пор, как я думал о загрузчиках классов, но IIRC .loadClass() будет преимущественно пытаться загружаться с самого основного загрузчика классов, а реальный java.utilпакет должен быть предоставлен загрузчиком классов начальной загрузки, что дает ему более высокий приоритет, чем все, что вы определяете в своем приложении.

...