Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 块作用域变量_Java_Compiler Errors_Scope - Fatal编程技术网

Java 块作用域变量

Java 块作用域变量,java,compiler-errors,scope,Java,Compiler Errors,Scope,这将编译 class X { public static void main(String args[]) { { int a = 2; } { int a = 3; } } } 这不会 class X { public static void main(String args[]) { int a =

这将编译

class X
{  
    public static void main(String args[])
    {
        {
            int a = 2;
        }
        {
            int a = 3;
        }       
    }
}
这不会

class X
{  
    public static void main(String args[])
    {

        int a = 2;

        {
            int a = 3;
        }       
    }
}

我希望两者都能编译(也许这就是C的工作方式?)。由于无法在块中声明与外部块中的变量同名的变量,原因是什么?

因为在第二种情况下,
在静态块中是已知的,所以您试图重新声明它。编译器不允许您这样做:

public static void main(String args[]) {
    {
       int a = 2; //a is known only here
    }             //a will be freed
    {
       int a = 3; //you can declare it again here
    }       
}

Java不允许在一个变量的作用域内有两个同名的变量

在第二种情况下:

int a = 2;

{
  // the outer 'a' is still in scope
  int a = 3; // so this is a redeclare <-- nooo!
} 
inta=2;
{
//外部“a”仍在范围内
int a=3;//这是一个重新声明
在上面的示例中,您在方法
main()
中声明了
a
。从声明到方法结束,将声明
a
。在这种情况下,您无法在代码块中重新声明a

下面,您在一个块中声明
a
。它只在内部已知

public static void main(String args[])
{
    { 
        int a = 2; // I know a
        // I know a
    }
    // Who is a?
    {

        int a = 3; // I know a!
    }       
}

简单的回答是:因为这是Java语言的定义方式

您可能会从其他语言中使用这种所谓的语言。但是,Java语言的发明者认为这是一个他们不希望在他们的语言中使用的尴尬特性:

此限制有助于检测一些其他方面非常模糊的bug

但是,您可以在Java的其他地方找到阴影,正如作者在JLS的同一部分中所述:

对于局部变量对成员的跟踪也有类似的限制 判断为不切实际,因为在超类中添加成员 可能导致子类必须重命名局部变量。相关 考虑因素对局部变量的阴影设置了限制 嵌套类的成员,或局部变量的局部阴影 嵌套类中声明的变量也没有吸引力

这意味着在实践中,以下准则是合法的:

class A {
   int x = 0;
   void m() {
     int x = 10; // Shadows this.x
   }
}
正如作者所描述的,允许通过声明具有相同名称的方法局部变量来隐藏实例变量,因为可能有人在某一天扩展了
a
的功能,如果隐藏是非法的,您将无法再编译类
B

class B extends A {
   void m() {
     int x = 10; // Shadows A.this.x if A declares x
   }
}

如果你考虑一种C语言,允许在其中进行遮蔽,你可以找到这样的笨拙代码:

int x;
int main() 
{
  {
    int x = 0;
    {
      extern int x;
      x = 1;
    }
    printf("%d\n", x); // prints 0
  }
  printf("%d\n", x); // prints 1
  return 0;
}

这个程序不太容易理解,因此可能不会产生预期的结果,这要归功于变量阴影。

在Java中,所有局部变量都将存储在堆栈上

class X
{  
public static void main(String args[])
{
   int a = 2;    // At this point var 'a' is stored on Stack
   {
       /*
       Now as the prev. 'main method is not yet complete so var 'a' is still present on the Stack. So at this point compiler will give error "a is already defined in main(java.lang.String[])" 
        */
       int a = 3;   

   }
 }
}
希望这对你有帮助


感谢

小心使用该语句
Java不允许您在另一个作用域内有两个同名变量。
这只适用于@SotiriosDelimanolis,您引用的链接如何支持您的语句?@flow2k它不支持。它只定义了局部变量和参数。作用域已定义。这完全是错误的。Compiled代码不知道局部变量的名称,它只知道索引。此外,变量不一定同时位于堆栈上。每个方法帧都有一个操作数堆栈和一个局部变量数组。因此,在Java中,所有局部变量都存储在堆栈上是不准确的。关于这个
int x=10;//Shadows A.this.x如果A在上面的
class A
定义中声明了x
,这是否意味着当我在A中打印
x
时,直到打印
10
0
为止,因为它打印
0
?不要在意上面的^^^得到了
阴影
的内容。如果我没有弄错,这意味着
覆盖了外部范围同名变量
class X
{  
public static void main(String args[])
{
   int a = 2;    // At this point var 'a' is stored on Stack
   {
       /*
       Now as the prev. 'main method is not yet complete so var 'a' is still present on the Stack. So at this point compiler will give error "a is already defined in main(java.lang.String[])" 
        */
       int a = 3;   

   }
 }
}