我有以下代码,它会抛出下面给出的错误。当'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
答案 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
类型的引用,它甚至不能保证引用类型。背景很重要。