块作用域变量

6pp0gazn  于 2021-07-06  发布在  Java
关注(0)|答案(5)|浏览(338)

这将编译

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的工作方式?)。为什么不能在块中声明与外部块中的变量同名的变量?

ldxq2e6h

ldxq2e6h1#

简单的回答是:因为这是jls中定义java语言的方式§6.4.
您可能会从其他语言使用这种所谓的变量阴影是允许的。然而,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;
}

由于变量阴影的存在,这个程序并不容易执行,因此可能不会产生预期的结果。

628mspwn

628mspwn2#

在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;   

   }
 }
}

希望这对你有帮助
谢谢

ebdffaop

ebdffaop3#

java不允许在一个变量的作用域内有两个同名的变量。
在第二种情况下:

int a = 2;

{
  // the outer 'a' is still in scope
  int a = 3; // so this is a redeclare <-- nooo!
}

但是,在第一种情况下,每个 a 包含在自己的范围内,所以一切都很好。

rpppsulh

rpppsulh4#

public static void main(String args[])
{
    int a = 2; // I know a
    // I know a
    {
        // I know a
        int a = 3; // There can be only one a!
    }       
}

在上面的示例中,您声明 a 在你的方法中 main() . 从声明到方法结束, 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!
    }       
}
vi4fp9gy

vi4fp9gy5#

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

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
    }       
}

相关问题