为什么一个try / catch块创建新的变量范围是什么?(Why does a Try/Catch

2019-06-17 12:50发布

例如:

try
{
    SomeObject someObject = new SomeObject();
    someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod(); //can't access someObject!

但是你可以在之前声明它try/catch块,然后它工作正常:

SomeObject someObject;
try
{
    someObject = new SomeObject();
    someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod(); //works fine

我只是想知道设计的原因。 为什么在对象中创建try/catch块不在范围内的方法的休息吗? 也许我不理解深处一个怎样try/catch作品除了刚看完的Exceptions抛出。

Answer 1:

为什么对象的try / catch块内创建不在范围内的方法的休息吗?

他们是。 该内声明的变量 try/catch块不在其包含块范围,出于同样的原因,所有其它的变量声明是局部的在其发生范围:这是规范如何定义它。 :-)(下面更多,包括对您的评论的回复。)

这里有一个内创建的对象try/catch这是它的外部访问:

SomeObject someObject = null;
try
{
    someObject = new SomeObject();
    someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod(); // This is fine -- unless the SomeObject
                            // constructor threw the exception, in which
                            // case someObject will be null

注意区别。 其中被声明变量定义,其中存在的范围,而不是在其中创建对象

但基于该方法姓名及以上,对于比较有用的结构将是:

SomeObject someObject = new SomeObject();
try
{
    someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod();

回复您的评论:

我想我很困惑,为什么另一范围甚至已经对try / catch块创建。

在Java中,所有块创建范围。 的身体if ,一个身体else ,一个的while ,等等-它们都创建一个新的,嵌套的变量范围:

if (foo) {
    SomeObject bar = new SomeObject();
}
bar.doSomething(); // <== Compilation error, `bar` is not defined

(事实上​​,即使没有任何控制结构的方块创建一个。)

如果你仔细想想,这是有道理的:有些模块是有条件的,就像一个定义的身体ifwhile 。 另外,在上述ifbar可以是或不是已被宣布(取决于的值foo ),它是没有意义的,因为过程的编译器没有的运行时间值的概念foo 。 所以可能的一致性,爪哇的设计师就具有所有块创建一个新的嵌套范围。 (JavaScript的的设计者走了另外的方式-没有块范围可言,然而,尽管它被添加-和方法迷惑人)



Answer 2:

在Java中,任何时候你有一个{ }对,你可以创建一个新的范围。

考虑以下

class ScopeTest {
    public static void main(String[] args) {
        int i = 0;
        { int j = 0; System.out.println(j); }
        { int j = 2; System.out.println(j); }
    }
}

该try / catch语句只是遵循这个成语,并强制执行{ }对被创建。

对您的非括号的if语句的后续回应,考虑:

class MultiRTree {
    public static void main(String...args) {
        boolean b = args.length == 0;
        if(b) String s = new String("hello");
    }
}

结果是

c:\files\j>javac ScopeTest.java
ScopeTest.java:4: not a statement
        if(b) String s = new String("hello");
              ^
ScopeTest.java:4: ';' expected
        if(b) String s = new String("hello");
                    ^
2 errors

然而,这将编译就好了。

class ScopeTest {
    public static void main(String...args) {
        boolean b = args.length == 0;
        if(b) new String("hello");
    }
}

为什么会这样,根据JLS第14章,第9,如果被定义为:

IfThenStatement:
    if ( Expression ) Statement

和语句被定义为(14.5)

Statement:
    StatementWithoutTrailingSubstatement
    LabeledStatement
    IfThenStatement
    IfThenElseStatement
    WhileStatement
    ForStatement

StatementWithoutTrailingSubstatement:
    Block
    EmptyStatement
    ExpressionStatement
    AssertStatement
    SwitchStatement
    DoStatement
    BreakStatement
    ContinueStatement
    ReturnStatement
    SynchronizedStatement
    ThrowStatement
    TryStatement

因此,一个块,表达式语句或空语句这些只是罚款。 但声明(在第6章中定义)是不是在声明的语法。



Answer 3:

一个变量或对象的范围是在范围中定义它(通过花括号{}中定义的)。

由于尝试catch启动一个新的范围,其中有些错误可以引发如此尝试捕捉内部定义的对象以外无法获得它的范围。



Answer 4:

try/catch产生的原因很简单,它是一个块级元素的新范围。 事实上,简单地把{}只是随机的方法中会创建新的代码块与它自己的局部范围。



Answer 5:

你使用一个支架每次“{”你表达在C ++和Java的新范围。 你尝试尝试的操作需要一定的内部设置和范围的名称,可以快速跳回了try块没有大量的清理工作。

有些语言让你访问这些变量的作用域范围之外,只要不存在名称冲突(例如Python中),但是这需要一个稍微不同的内部堆叠结构与仍可增加尝试捕捉的费用不管。

另外它的范围定义只是如何在Java定义 - 许多其他的答案中指出。



文章来源: Why does a Try/Catch block create new variable scope?