How to refer to a class when both simple and fully-qualified names clash

依然范特西╮ 提交于 2019-12-21 07:28:50

问题


Consider the following pathological example:

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?
  }
}

The two instances created in the constructor are of the nested classes.

But how might I refer to the java.util.ArrayList that we all know and love in the same class? We can't import it, and we can't use the fully-qualified name, as the nested class symbols would be used instead.

What can we do in this case? (Other than the obvious - stop using such wantonly evil names for the nested classes).


回答1:


You can no longer directly reference java.util.ArrayList if you've done the 2 things you've done:

  1. Hide the simple name ArrayList with a static nested class in scope.
  2. Hide the fully qualified name java.util.ArrayList with a class ArrayList nested within class util, nested within nested class java.

You can't even "split" the import in an attempt to use a "partially qualified" import.

import java.*;

...

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

You can import java.*;, but that is worthless; no classes are defined in the java package directly.

However, you can reference the class java.util.ArrayList indirectly because it's not final. Outside the scope of the class Ideone, declare a subclass with a different name.

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

Then you can refer to that class and program to the interface:

List<Integer> al = new AnArrayList<>();  // won't print !! or Here



回答2:


I'm going to go out on a limb and say that it's not possible to refer to it from within Ideone. The only solution that I see is to create another class Idetwo (which is a nestmate of Ideone (i.e. it resides in the same file)) and return a java.util.ArrayList from there for use in 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;
    }
}

And you'd just change your Ideone's main method to something like:

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

Output:

!!
Here
1
2
3

Note: With this method, importing java.util.ArrayList will work fine. However, if you were to call List<Integer> list = Idetwo.getList(); inside Ideone's main method, you need to import java.util.*, as individual imports will not work (interestingly).




回答3:


Have you tried

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

It's been a long time since I've thought about classloaders, but IIRC .loadClass() will preferentially try to load from the most fundamental classloader, and the real java.util package should be provided by the bootstrap classloader, which gives it higher precedence than anything you define in your application.




回答4:


That's why packages start with lower case letters, and types with upper case letters, since the very first edition of the official code conventions for java. I don't think I have ever seen java code break this convention.

But you can refer to the inner type from the outside using it's fully qualified name:

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

When you have to refer to the outer type from inside, you can probably change that source file to comply with Java naming guidelines.



来源:https://stackoverflow.com/questions/50633759/how-to-refer-to-a-class-when-both-simple-and-fully-qualified-names-clash

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!