在我的项目中使用预定义的 class 名称字符串

using predefined class name String in my project

我有下面的代码,它会抛出下面给出的错误。当 'String[] args' 替换为 'java.lang.String[] args' 时,它不会抛出错误并运行方法 s1.method1().

问题:为什么本地字符串优先于 java.lang.String? 根据委派模型,Bootstrap class 加载程序获得优先权并在加载测试 class 之前加载 java.lang.String。我在这里错过了什么吗?请指出有关此行为的任何参考资料。

Test.java:

package diff;
class String {

    public void method1(){
    System.out.println("in my method");
    }
}

class Test {
    public static void main(String[] args){
        String s1 = new String();
        s1.method1();
    }
}

错误:在classdiff.Test中找不到主要方法,请将主要方法定义为: public static void main(String[] args) 或 JavaFX 应用程序 class 必须扩展 javafx.application.Application

问题:为什么本地字符串优先于 java.lang.String?

本地 name masks java.lang 中的那个。 java.lang 包由编译器为每个程序隐式导入,但是您不能将 java.lang.String 用作 String 因为您 屏蔽了 名称 String。如您所述,您可以使用 java.lang.String 重命名您的 String class (简而言之,不要添加自定义 classes与 java.lang 中的 class 个名称冲突)。这不是 class-loader 问题,因为编译后所有 classes 在字节码中都是完全合格的。

你必须区分类型和名称。您创建了一个名为 diff.String 的 class,它不会与 java.lang.String 发生冲突。 class 加载程序委托在这里无关紧要;甚至不可能定义冲突的 java.lang.String class,因为以 java. 开头的名称是保留的。

当简单名称 String 得到解析时,本地范围具有优先权。顺便说一下,这发生在 compile-time,这是 class 加载器在这里不相关的另一个原因。还有一个优先规则,variable > class > package,它允许下面的怪异代码:

Integer String = 42;
String Integer = ""+String.intValue();
System.out.println(Integer);

第一个语句声明了一个名为 StringInteger 类型的变量。在第二个语句中,第一个“String”被解析为一个类型,因为这个位置不允许使用变量,而对于名称的第二次出现,在 String.intValue() 中,变量 String 优先。同样,在第三条语句中,Integer 被解析为变量 Integer.

一般来说,程序员应该遵循只让 class 名称以大写字母开头的约定,这大大减少了了解这些规则的需要。

要点是,并非每次出现简单名称 String 都暗示对类型 java.lang.String 的引用,甚至不能保证引用类型。上下文很重要。