Java 简单名称和完全限定名称冲突时如何引用类

Java 简单名称和完全限定名称冲突时如何引用类,java,language-specifications,Java,Language Specifications,考虑以下病理学示例: class Ideone { static class ArrayList<T> { ArrayList() { System.out.println("!!"); } } static class java { static class util { static class ArrayList<T> { ArrayList() { System.ou

考虑以下病理学示例:

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?
  }
}
类表意符{
静态类数组列表{
ArrayList(){
System.out.println(“!!”);
}
}
静态类java{
静态类util{
静态类数组列表{
ArrayList(){
System.out.println(“此处”);
}
}
}
}
公共静态void main(字符串[]args){
新的ArrayList();
新的java.util.ArrayList();
//我可以参考“常用”java.util.ArrayList吗?
}
}
构造函数中创建的两个实例是嵌套类

但是,我怎么能提到我们在同一个班级里都知道和热爱的东西呢?我们不能导入它,也不能使用完全限定名,因为将使用嵌套的类符号

在这种情况下我们能做什么?(除了显而易见的-停止对嵌套类使用这种肆意邪恶的名称)。

您尝试过吗

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

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

我要冒一个险说,从
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;
    }
}
输出:

!!
Here
1
2
3

注意:使用此方法,导入
java.util.ArrayList
会很好。但是,如果要调用
List List=Idetwo.getList()
在Ideone的主要方法中,您需要导入
java.util.*
,因为单个导入将不起作用(有趣的是)。

这就是为什么程序包以小写字母开始,而类型以大写字母开始,因为。我认为我从未见过java代码打破这种惯例

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

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

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

如果您已经完成了以下两项工作,则不能再直接引用
Java.util.ArrayList

  • 使用范围中的静态嵌套类隐藏简单名称
    ArrayList
  • 使用嵌套在类
    util
    中的类
    ArrayList
    隐藏完全限定名
    java.util.ArrayList
    ,嵌套在嵌套类
    java
  • 您甚至不能在尝试使用“部分限定”导入时“拆分”导入

    然后您可以将该类和程序引用到接口:

    List<Integer> al = new AnArrayList<>();  // won't print !! or Here
    
    List al=new AnArrayList();//不会打印!!还是在这里
    
    你有理由相信有解决办法吗?@shmosel并不特别。我只是在做一些容易出错的检查时,想到了一些奇怪的导入案例。我希望看到一位语言架构师回答这个问题。如果您遵循标准,即所有小写的包名和混合大小写的类名,那么这个问题就不会发生。命名约定的存在是有原因的。@Andreas我同意;但我问的是语言允许什么,而不是约定使用什么。很好的尝试,但我说的是“在同一个类中”,而不是“在同一个编译单元中”;)@Andy Turner Darn,错过了;)请参阅我对@Andreas'评论的回复:“我问的是语言允许的内容,而不是惯例使用的内容”。如果您调用
    loadClass
    ,而不是
    findClass
    ,这应该可以实现。当然,通过使用类似于
    Stream.of().collect(Collectors.toList())
    @AndyTurner的东西,您可以得到一个实际的
    java.util.ArrayList
    ,听起来您应该回答自己的问题。我查找了
    收集器的源代码。toList
    ,它使用了
    ArrayList::new
    ,确认了您的声明。也许吧。这并不是我想问的问题的答案,你能引用这个类型吗,而不是如何得到这个类型的实例。
    import java.*;
    
    ...
    
    // This doesn't work!
    new util.ArrayList<>();
    
    class AnArrayList<T> extends java.util.ArrayList<T> {}
    
    List<Integer> al = new AnArrayList<>();  // won't print !! or Here