14

考虑以下病态示例:

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

4 回答 4

3

我将四处走动,说不可能从内部引用它Ideone。我看到的唯一解决方案是创建另一个类Idetwo(它是的嵌套对象Ideone(即它驻留在同一个文件中))并java.util.ArrayList从那里返回 a 以用于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();insideIdeone的 main 方法,则需要 import java.util.*,因为单独的导入将不起作用(有趣的是)。

于 2018-05-31T23:09:20.147 回答
3

java.util.ArrayList如果您完成了已完成的 2 件事,则无法再直接引用:

  1. ArrayList使用范围内的静态嵌套类隐藏简单名称。
  2. 使用嵌套在类中java.util.ArrayList的类隐藏完全限定名称,嵌套在嵌套类中。ArrayListutiljava

您甚至不能“拆分”导入以尝试使用“部分限定”导入。

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
于 2018-05-31T23:11:34.923 回答
2

你有没有尝试过

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

很久没有考虑类加载器了,但是 IIRC.loadClass()会优先尝试从最基本的类加载器加载,真正的java.util包应该由引导类加载器提供,这比你在应用程序中定义的任何东西都具有更高的优先级.

于 2018-05-31T23:00:32.233 回答
1

这就是为什么包以小写字母开头,类型以大写字母开头的原因,因为java 官方代码约定的第一版。我认为我从未见过 java 代码打破了这个约定。

但是您可以使用它的完全限定名称从外部引用内部类型:

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

当您必须从内部引用外部类型时,您可能可以更改该源文件以符合 Java 命名准则。

于 2018-05-31T23:10:59.750 回答