java 名称相同但类型不同的变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13657026/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 13:31:04  来源:igfitidea点击:

Variables having same name but different type

javanaming-conventions

提问by Extreme Coders

I have read herethat in Java it is possible for two variables having same name but different type to co-exist in the same scope. What I mean is this

我在这里读到,在 Java 中,两个具有相同名称但不同类型的变量可以在同一范围中共存。我的意思是这个

class test
{
    private int x;
    private double x;
}

But all java IDE do not allow such code. I want to know whether such a code is really syntactically correct, or simply the IDE do not allow such code to prevent ambiguity.

但是所有的java IDE 都不允许这样的代码。我想知道这样的代码在语法上是否真的正确,或者只是 IDE 不允许这样的代码来防止歧义。

Anyway here is the extract from the website

无论如何,这是网站的摘录

"If you're lucky, you might be able to recompile the output from Jad. However, the Java VM has more lenient rules for variable naming than the Java language itself. For instances, a valid class file can have several variables named 'a', as long as they have different types. If you decompile such a class, the source code you get will not be valid.

JAD will usually rename the offending fields, and make a recompilable file... the only problem being that the recompiled file won't be compatible with the original classes."

“如果幸运的话,你可能能够重新编译 Jad 的输出。然而,Java VM 对变量命名的规则比 Java 语言本身更宽松。例如,一个有效的类文件可以有多个名为 'a 的变量',只要它们的类型不同。如果你反编译这样的类,你得到的源代码将是无效的。

JAD 通常会重命名有问题的字段,并制作一个可重新编译的文件……唯一的问题是重新编译的文件与原始类不兼容。”

采纳答案by Evgeniy Dorofeev

You cannot have variables having same name (but different type) to exist in the same scope. Consider if it was possible then how would the java compiler determine which one you meant.

您不能让具有相同名称(但不同类型)的变量存在于同一范围内。考虑一下是否可能,那么 java 编译器将如何确定您的意思。

Consider this code snippet

考虑这个代码片段

class test
{
    private int x;
    private double x;

    test() //constructor
    {
        System.out.println(x); //Error cannot determine which x you meant
    } 
}

The java compiler cannot understand which x you are actually referring to. So such a code is not syntactically correct and not compilable.

java 编译器无法理解您实际指的是哪个 x。所以这样的代码在语法上不正确且不可编译。

However there exists tools such as ClassEditorwhich can modify the generated class file after it is created. There it is possible to change the name two variables to same.

但是,存在ClassEditor等工具可以在创建后修改生成的类文件。可以将两个变量的名称更改为相同。

However such a class is not necessarily runnable by the java jvm.

然而,这样的类不一定可以由 java jvm 运行。

The software which you have quoted i.e JADcan rename such duplicate named variables in the class file so that the source code which you will be getting will actually be syntactically correct

您引用的软件 ieJAD可以在类文件中重命名此类重复命名的变量,以便您将获得的源代码实际上在语法上是正确的

回答by assylias

According to the specification of the language (JLS 8.3):

根据语言规范(JLS 8.3):

It is a compile-time error for the body of a class declaration to declare two fields with the same name.

类声明的主体声明具有相同名称的两个字段是编译时错误。

The statement that you've quoted is about a class file (i.e. a compiled file, not the source code).

您引用的语句是关于类文件的(即编译文件,而不是源代码)。

回答by Evgeniy Dorofeev

Of course you cannot have int x and long x fields in the same class, just as you cannot have two methods with the same name and parameter list. But this is at the source level. JVM and bytecode have different rules. Consider this:

当然,在同一个类中不能有 int x 和 long x 字段,就像不能有两个具有相同名称和参数列表的方法一样。但这是在源代码级别。JVM 和字节码有不同的规则。考虑一下:

package test;

包装测试;

public class Test {
    static int x;

    @Override
    protected Test clone() throws CloneNotSupportedException {
        return this;
    }

    public static void main(String[] args) {
        int y = x;
    }
}

If you use a bytecode outline tool (I've used Andrey Loskutov's plugin for Eclipse) you will see in this line int Test.main()

如果您使用字节码大纲工具(我使用了 Andrey Loskutov 的 Eclipse 插件),您将在这一行中看到 int Test.main()

GETSTATIC test/Test.x : I

This is how JVM loads value from field x, its full name is "test/Test.x : I". That gives you a hint that the field value is present in the field full name.

这就是 JVM 从字段 x 加载值的方式,它的全名是“test/Test.x : I”。这会提示您字段值存在于字段全名中。

It's no secret that javac is not the only means to create a class, there are tools/libraries to create bytecode directly, and they are free to create classes with fields with the same name but different type. Same goes for JNI.

javac 不是创建类的唯一方法,这已经不是什么秘密了,有直接创建字节码的工具/库,它们可以自由地创建具有相同名称但不同类型的字段的类。JNI 也是如此。

It's hard to show a working example of what I am trying to prove. But let's consider methods, a similar issue. Bytecode analisys shows that there are two methods in Test class with the same name and parameters which is not allowed by JLS:

很难展示我试图证明的工作示例。但是让我们考虑方法,一个类似的问题。字节码分析显示Test类中有两个同名同参数的方法是JLS不允许的:

protected clone()Ltest/Test; throws java/lang/CloneNotSupportedException 

protected volatile bridge clone()Ljava/lang/Object; throws java/lang/CloneNotSupportedException 

The "bridge" method was added by javac because Test.clone() returns Test and this means it does not override Object.clone() which returns Object and this is because JVM thinks these two are different methods

javac 添加了“bridge”方法是因为 Test.clone() 返回 Test ,这意味着它不会覆盖返回 Object 的 Object.clone() ,这是因为 JVM 认为这两个是不同的方法

1 clone()Ltest/Test;
2 clone()Ljava/lang/Object;