tre*_*r-e 44 java scope try-catch
例如:
try
{
SomeObject someObject = new SomeObject();
someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod(); //can't access someObject!
Run Code Online (Sandbox Code Playgroud)
但你可以在try/catch块之前声明它然后它工作正常:
SomeObject someObject;
try
{
someObject = new SomeObject();
someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod(); //works fine
Run Code Online (Sandbox Code Playgroud)
我只是想知道这个的设计原因.为什么在try/catch块内创建的对象不在方法的其余部分范围内?也许我不会深入了解try/catch除了观看Exceptions投掷之外的工作方式.
T.J*_*der 50
为什么在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
Run Code Online (Sandbox Code Playgroud)
注意区别.当变量被声明定义了它的存在的范围,而不是其中对象被创建.
但基于上面的方法名称,更有用的结构是:
SomeObject someObject = new SomeObject();
try
{
someObject.dangerousMethod();
}
catch(Exception e)
{
}
someObject.anotherMethod();
Run Code Online (Sandbox Code Playgroud)
你的评论:
我想我为什么为try/catch块创建了另一个范围感到困惑.
在Java中,所有块都创建范围.的身体if,一个身体else的,while等等-它们都创建一个新的,嵌套的变量范围:
if (foo) {
SomeObject bar = new SomeObject();
}
bar.doSomething(); // <== Compilation error, `bar` is not defined
Run Code Online (Sandbox Code Playgroud)
(实际上,即使是没有任何控制结构的块也会创建一个.)
如果你考虑它,它是有道理的:有些块是有条件的,比如定义一个if或一个的主体while.在上面if,bar可能会或可能没有声明(取决于值foo),这没有任何意义,因为编译器当然没有运行时值的概念foo.因此,为了保持一致性,Java的设计人员会让所有块创建一个新的嵌套范围.(JavaScript的设计者走的是另一种方式 - 根本没有块范围,但是,虽然它被添加 - 但这种方法也让人感到困惑.)
在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); }
}
}
Run Code Online (Sandbox Code Playgroud)
try/catch只是遵循这个习惯用法,并强制{ }创建一对.
要回复您对非括号if语句的跟进,请考虑:
class MultiRTree {
public static void main(String...args) {
boolean b = args.length == 0;
if(b) String s = new String("hello");
}
}
Run Code Online (Sandbox Code Playgroud)
结果是
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
Run Code Online (Sandbox Code Playgroud)
但是,这将编译得很好.
class ScopeTest {
public static void main(String...args) {
boolean b = args.length == 0;
if(b) new String("hello");
}
}
Run Code Online (Sandbox Code Playgroud)
为什么会这样,根据JLS第14章第9节,如果定义为:
IfThenStatement:
if ( Expression ) Statement
Run Code Online (Sandbox Code Playgroud)
声明定义为(14.5)
Statement:
StatementWithoutTrailingSubstatement
LabeledStatement
IfThenStatement
IfThenElseStatement
WhileStatement
ForStatement
StatementWithoutTrailingSubstatement:
Block
EmptyStatement
ExpressionStatement
AssertStatement
SwitchStatement
DoStatement
BreakStatement
ContinueStatement
ReturnStatement
SynchronizedStatement
ThrowStatement
TryStatement
Run Code Online (Sandbox Code Playgroud)
那么块,表达式语句或空语句就可以了.但是声明(在第6章中定义)不在声明的语法中.
变量或对象的范围在范围内(由花括号{}定义),在该范围内定义它.
因为try catch启动了一个新的作用域,可以抛出一些错误,所以try catch中定义的对象在它的作用域之外是不可用的.
每次使用括号“{”时,您都在表示 C++ 和 Java 中的新作用域。您尝试尝试操作需要一些内部设置,并且定义名称范围允许快速跳出 try 块,而无需进行大量清理。
只要不存在名称冲突(例如在 Python 中),某些语言将允许您访问范围之外的那些范围变量,但这需要稍微不同的内部堆栈结构,并且无论如何仍然可能增加 try catch 的成本。
此外,它只是在 Java 中定义范围定义的方式——正如许多其他答案所指出的那样。
| 归档时间: |
|
| 查看次数: |
34531 次 |
| 最近记录: |