在我的项目中使用预定义的类名String

时间:2018-03-12 17:29:38

标签: java jvm classloader

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

问题:为什么本地String优先于java.lang.String? 根据委托模型,Bootstrap类加载器获取首选项,并在加载Test类之前加载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();
    }
}

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

2 个答案:

答案 0 :(得分:4)

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

java.lang中的本地name masks。编译器会为每个程序隐式导入java.lang包,但是您不能将java.lang.String用作String,因为您屏蔽了名称{{ 1}}。如您所知,您可以使用String 重命名您的java.lang.String课程(简而言之,请勿添加与String中的班级名称冲突的自定义类})。这不是类加载器问题,因为在编译之后,所有类都在字节代码中完全限定。

答案 1 :(得分:2)

您必须区分类型和名称。您已创建名为diff.String的类,该类不会与java.lang.String发生冲突。类加载器委托与此无关;甚至不可能定义冲突的java.lang.String类,因为保留以java.开头的名称。

当解析简单名称String时,本地范围具有优先权。顺便说一下,这发生在编译时,这是类加载器在这里不相关的另一个原因。还有另一个优先规则,变量>课程>包,它允许以下奇怪的代码:

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

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

通常,程序员应该遵循约定,只允许类名以大写字母开头,这大大减少了了解这些规则的需要。

要点是,并非每次出现简单名称Integer都意味着对Integer类型的引用,它甚至不能保证引用类型。背景很重要。