Java(显然)具有矛盾的作用域

Java(显然)具有矛盾的作用域,java,scope,Java,Scope,对于此代码示例,Java编译器不满意: public class Test1 { public static void main(String args[]) { int x = 99; { int x = 10; System.out.println(x); } System.out.println(x); } } 编者说: 错误:变量x已在方法main中定义(字符串[]) 但是,Java编译器对此完全满意: public cl

对于此代码示例,Java编译器不满意:

public class Test1 {
  public static void main(String args[]) {
    int x = 99;
    {
      int x = 10;
      System.out.println(x);
    }
    System.out.println(x);
  }
}
编者说:

错误:变量x已在方法main中定义(字符串[])

但是,Java编译器对此完全满意:

public class Test1 {
  public static void main(String args[]) {
    {
      int x = 10;
      System.out.println(x);
    }
    int x = 99;
    System.out.println(x);
  }
}
这在Java中有点疯狂。当我查找Java作用域规则时,我几乎总是看到编写者描述变量的作用域在它们所在的块级别内,但对象级别变量的实例除外,它们在实例生命周期中保留其值

它们都没有以解释Java编译器处理这里的代码示例的方式来解释规则。但正如我们从这两个明显的例子中所看到的,范围界定规则并不像每个人所描述的那样有效


请有人正确地解释一下,好让我正确地理解它吗?

这不是Java的问题。当第二个
x
被声明和使用时,作用域变量
x
已超出作用域。

我可以尝试解释,但不知道确切的规则

在第一个示例中,
x
在内部范围中都是已知的。这是不允许的

在第二个示例中,在内部范围中,外部
x
尚未定义。所以没有问题

int x = 99;
{
  int x = 10;   // variable x defined before is still available, so you can not define it again
  System.out.println(x);
}
System.out.println(x);
以及:

第一个代码中第一个
x
的范围在main方法中 因此
x
在方法中随处可见,这就是为什么它不允许 我们重新申报

其中,与在第二个代码中一样,第一个
x
的范围在块
{}
因此,由于此块外的
x
不可见或未知,因此允许声明第二个
x

public class Test1 {
  public static void main(String args[]) {
    {
      int x = 10;
      System.out.println(x);
    // x gets out of scope after this closing block
    }
    int x = 99;  // allowed because the first x got out of scope
    System.out.println(x);
  }
}

内部块级别存在于外部作用域级别,该级别已经有int(在第一种情况下),在第二种情况下,外部作用域级别还没有int(刚刚)。Nope和Nope。它工作得很完美,你可以从内部看到外部,但不能从外部看到内部。这就是它要添加到下面的答案中,有什么替代方案?您似乎认为,在第一个示例中,变量x的外部定义不应该在内部代码块中可见。对我来说,我的期望是两个代码示例都可以编译良好,即“内部x”只是与外部x完全不同的变量(这是事实,不管另一个名为“x”的变量是在外部范围内定义的),并且内部块中对“x”的任何引用都是对“内部x”的引用。另一方面,在编译器在我的第一个示例中抱怨之后(这是一个从我目前正在处理的一个较大程序中大大简化的示例),我很惊讶编译器接受了第二个示例。我确实明白了-但我觉得它不和谐。它没有什么奇怪或独特的地方。范围约束不是双向的。如果一个范围嵌套在另一个范围中,则子范围继承了父范围的可见性,但反之亦然。显然,这个简短的答案不足以实际回答问题
public class Test1 {
  public static void main(String args[]) {
    int x = 99;
    {
      int x = 10; // not allowed because the fist x is visible/known here
      System.out.println(x);
    }
    System.out.println(x);
  }
}
public class Test1 {
  public static void main(String args[]) {
    {
      int x = 10;
      System.out.println(x);
    // x gets out of scope after this closing block
    }
    int x = 99;  // allowed because the first x got out of scope
    System.out.println(x);
  }
}