在Java中,变量名可以与类名相同
在Java中,我可以声明一个变量,其名称与其类名完全相同。我认为这是一个如此令人困惑和奇怪的设计 因此,我在下面的代码片段中遇到了一个问题:编译器如何区分在Java中,变量名可以与类名相同,java,class,compiler-construction,Java,Class,Compiler Construction,在Java中,我可以声明一个变量,其名称与其类名完全相同。我认为这是一个如此令人困惑和奇怪的设计 因此,我在下面的代码片段中遇到了一个问题:编译器如何区分类名,它引用了变量名称或类名称 在运行结果中,编译器引用ClassName作为变量名 class ClassName{} public class Test { public static void main(String[] args){ ClassName ClassName = new ClassName();
类名
,它引用了变量名称或类名称
在运行结果中,编译器引用
ClassName
作为变量名
class ClassName{}
public class Test {
public static void main(String[] args){
ClassName ClassName = new ClassName();
System.out.println(ClassName); //ClassName@18fb53f6
}
}
编译器如何区分“类名”
因为有两个组件:变量类型和变量名称。声明类型为ClassName
的变量ClassName
。打字总是排在第一位。类不是第一类对象(这意味着不能有对类的引用),除非您进入反射(使用.class
属性)
因此,在print语句中:
System.out.println(ClassName);
这只能是变量System.out.println
接受一个对象引用,并且您有一个名为ClassName
的变量引用的对象,因此编译器可以解析它
我认为编译器唯一不明确的情况是,变量引用的对象的实例方法与类上的静态方法同名
public class SomeClass {
public void aMethod() {
System.out.println("A method!");
}
public static void aMethod() {
System.out.println("Static version!");
}
}
public class TestClass {
public static void main (String[] args) {
SomeClass SomeClass = new SomeClass();
SomeClass.aMethod(); // does this call the instance method or the static method?
}
}
我确信编译器会检测到歧义并以某种特定的方式(在Java规范中)处理它。可能是:
Java有很多规则来迫使你做合乎逻辑的事情,使代码易于遵循,但归根结底,它仍然是代码,你可以编写任何你想要的代码。没有任何语言规范或编译器可以阻止您编写令人困惑的代码。编译器可以根据上下文进行判断。在您给出的示例中:
ClassName ClassName = new ClassName();
1 2 3
它可以看到1是类型名的位置,因此它知道您指的是类。然后,2是期望变量名的位置,因此它知道这应该是变量名。3在new
关键字后面加括号,因此它必须是类的名称
System.out.println( ClassName );
在本例中,ClassName
位于参数传递的上下文中。类型名不能作为参数传递,因此必须表示变量的名称
为了自娱自乐,您可以将打印语句更改为:
System.out.println( ClassName.class );
将鼠标光标悬停在ClassName
上,编译器会将其识别为类的名称。然后将其更改为:
System.out.println( ClassName.getClass() );
再次将光标悬停,现在可以看到它将其识别为变量名。这是因为.class
只能应用于类型名称,而getClass()
只能应用于对象引用。在这两种情况下,print语句的结果是相同的,但通过不同的机制
因此编译器在这里没有问题。但你是对的,人类无法阅读。约定是变量和方法的名称必须以小写字母开头,而类型名称必须以大写字母开头。遵守本公约将确保不会出现此类可读性问题
我不能确切地说为什么Java的作者选择不执行这个约定(也就是说,如果类型名以小写字母开头,或者变量/方法名以大写字母开头,则给出一个编译器错误),但是我推测他们不想让任何事情成为实际的错误,除非它实际上会导致编译器的歧义。编译错误被认为是指使编译器无法工作的问题
ClassName ClassName = new ClassName();
若你们学习编译器设计课程,你们会知道有一个词法分析步骤。在这一步中,您将为您的语言编写语法。例如:
ClassName variableName = new ClassName();
所以在上面的例子中,编译器可以理解第二个类名是变量
当您执行以下操作时:
ClassName.doSomething();
Java将类名理解为变量而不是类。这种设计没有任何限制doSomething()
既可以是静态方法,也可以只是实例方法
如果Java将这里的ClassName理解为类,那么doSomething()
就不能是实例方法。也许是因为这样,Java创建者选择了上面的设计:ClassName作为变量
但是,如果变量名不能与它们的类同名,那么问题是什么呢。下面是一个例子:
ClassA ClassB = new ClassA();
ClassB.callMethodInClassB(); // should compile error or not ???!!!
问题仍然存在。误导仍然存在。因此,新的设计应该是:
任何变量名称都不应与**任何**类名同名。
你会看到,这句话使一种语言更难理解,也没有很好的定义。根据以上的证明,我认为当你做一些事情时,比如:A A=newa()代码>下方