⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 15.doc.html

📁 java语言规范
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<a name="18868"></a>	}
<a name="18869"></a>
	static int forgetIt() throws Exception {
<a name="50187"></a>		throw new Exception("I'm outta here!");
<a name="50189"></a>	}
<a name="18870"></a>}
</pre><a name="18858"></a>
prints:
<p><pre><a name="36046"></a>
java.lang.Exception: I'm outta here!
<a name="36047"></a>Now j = 1
</pre><a name="18885"></a>
because the left-hand operand <code>forgetIt()</code> of the operator <code>/</code> throws an exception 
before the right-hand operand and its embedded assignment of <code>2</code> to <code>j</code> occurs.
<p><a name="18740"></a>
<h3>15.6.2    Evaluate Operands before Operation</h3>
<a name="18749"></a>
Java also guarantees that every operand of an operator (except the conditional 
operators <code>&amp;&amp;</code>, <code>||</code>, and <code>?</code> <code>:</code>) appears to be fully evaluated before any part of the 
operation itself is performed.
<p><a name="32910"></a>
If the binary operator is an integer division <code>/</code> <a href="15.doc.html#5047">(&#167;15.16.2)</a> or integer remainder <code>%</code> <a href="15.doc.html#24956">(&#167;15.16.3)</a>, then its execution may raise an <code>ArithmeticException</code>, but this exception is thrown only after both operands of the binary operator have been evaluated and only if these evaluations completed normally.<p>
<a name="36160"></a>
So, for example, the program:<p>
<pre><a name="36161"></a>
class Test {
<a name="36162"></a>
	public static void main(String[] args) {
<a name="36163"></a>		int divisor = 0;
<a name="36164"></a>		try {
<a name="36165"></a>			int i = 1 / (divisor * loseBig());
<a name="36166"></a>		} catch (Exception e) {
<a name="36167"></a>			System.out.println(e);
<a name="36168"></a>		}
<a name="36169"></a>	}
<br><a name="36170"></a>
	static int loseBig() throws Exception {
<a name="36171"></a>		throw new Exception("Shuffle off to Buffalo!");
<a name="36172"></a>	}
<br><a name="36173"></a>}
</pre><a name="36174"></a>
always prints:
<p><pre><a name="36175"></a>java.lang.Exception: Shuffle off to Buffalo!
</pre><a name="36176"></a>
and not:
<p><pre><a name="36177"></a>java.lang.ArithmeticException: / by zero
</pre><a name="36178"></a>
since no part of the division operation, including signaling of a divide-by-zero 
exception, may appear to occur before the invocation of <code>loseBig</code> completes, even 
though the implementation may be able to detect or infer that the division operation
would certainly result in a divide-by-zero exception.
<p><a name="23213"></a>
<h3>15.6.3    Evaluation Respects Parentheses and Precedence</h3>
<a name="23217"></a>
Java implementations must respect the order of evaluation as indicated explicitly 
by parentheses and implicitly by operator precedence. An implementation may 
not take advantage of algebraic identities such as the associative law to rewrite 
expressions into a more convenient computational order unless it can be proven 
that the replacement expression is equivalent in value and in its observable side 
effects, even in the presence of multiple threads of execution (using the thread 
execution model in <a href="17.doc.html#26250">&#167;17</a>), for all possible computational values that might be 
involved.
<p><a name="23218"></a>
In the case of floating-point calculations, this rule applies also for infinity and not-a-number (NaN) values. For example, <code>!(x&lt;y)</code> may not be rewritten as <code>x&gt;=y</code>, because these expressions have different values if either <code>x</code> or <code>y</code> is NaN.<p>
<a name="23219"></a>
Specifically, floating-point calculations that appear to be mathematically associative are unlikely to be computationally associative. Such computations must not be naively reordered. For example, it is not correct for a Java compiler to rewrite <code>4.0*x*0.5</code> as <code>2.0*x</code>; while roundoff happens not to be an issue here, there are large values of <code>x</code> for which the first expression produces infinity (because of overflow) but the second expression produces a finite result.<p>
<a name="238102"></a>
So, for example, the test program:<p>
<pre><a name="23224"></a>
class Test {
<a name="23225"></a>
	public static void main(String[] args) {
<a name="23226"></a>		double d = 8e+307;
<a name="23227"></a>		System.out.println(4.0 * d * 0.5);
<a name="23228"></a>		System.out.println(2.0 * d);
<a name="23229"></a>	}
<a name="23230"></a>}
</pre><a name="23231"></a>
prints:
<p><pre><a name="23232"></a>
Infinity
<a name="23233"></a>1.6e+308
</pre><a name="23234"></a>
because the first expression overflows and the second does not.
<p><a name="21009"></a>
In contrast, integer addition and multiplication <i>are</i> provably associative in Java; for example <code>a+b+c</code>, where <code>a</code>, <code>b</code>, and <code>c</code> are local variables (this simplifying assumption avoids issues involving multiple threads and <code>volatile</code> variables), will always produce the same answer whether evaluated as <code>(a+b)+c</code> or <code>a+(b+c)</code>; if the expression <code>b+c</code> occurs nearby in the code, a smart compiler may be able to use this common subexpression.<p>
<a name="23789"></a>
<h3>15.6.4    Argument Lists are Evaluated Left-to-Right</h3>
<a name="23790"></a>
In a method or constructor invocation or class instance creation expression, argument
expressions may appear within the parentheses, separated by commas. Each 
argument expression appears to be fully evaluated before any part of any argument 
expression to its right.
<p><a name="23791"></a>
Thus:<p>
<pre><a name="23792"></a>class Test {
</pre><pre><a name="50195"></a>
	public static void main(String[] args) {
<a name="23793"></a>		String s = "going, ";
<a name="23794"></a>		print3(s, s, s = "gone");
<a name="23795"></a>	}
<a name="23796"></a>
	static void print3(String a, String b, String c) {
<a name="23797"></a>		System.out.println(a + b + c);
<a name="23798"></a>	}
<a name="23799"></a>}
</pre><a name="23800"></a>
always prints:
<p><pre><a name="23801"></a>going, going, gone
</pre><a name="23802"></a>
because the assignment of the string <code>"gone"</code> to <code>s</code> occurs after the first two arguments
to <code>print3</code> have been evaluated.
<p><a name="23803"></a>
If evaluation of an argument expression completes abruptly, no part of any argument expression to its right appears to have been evaluated.<p>
<a name="23804"></a>
Thus, the example:<p>
<pre><a name="23805"></a>
class Test {
<a name="23806"></a>	static int id;
<a name="23807"></a>	public static void main(String[] args) {
<a name="23808"></a>		try {
<a name="23809"></a>			test(id = 1, oops(), id = 3);
<a name="23810"></a>		} catch (Exception e) {
<a name="23811"></a>			System.out.println(e + ", id=" + id);
<a name="23812"></a>		}
<a name="23813"></a>	}
<br><a name="23814"></a>	static int oops() throws Exception {
<a name="23815"></a>		throw new Exception("oops");
<a name="23816"></a>	}
<br><a name="23817"></a>	static int test(int a, int b, int c) {
<a name="23818"></a>		return a + b + c;
<a name="23819"></a>	}
<br><a name="23820"></a>}
</pre><a name="23821"></a>
prints:
<p><pre><a name="23822"></a>java.lang.Exception: oops, id=1
</pre><a name="23823"></a>
because the assignment of <code>3</code> to <code>id</code> is not executed.
<p><a name="23451"></a>
<h3>15.6.5    Evaluation Order for Other Expressions</h3>
<a name="23452"></a>
The order of evaluation for some expressions is not completely covered by these 
general rules, because these expressions may raise exceptional conditions at times 
that must be specified. See, specifically, the detailed explanations of evaluation 
order for the following kinds of expressions:
<p><ul><a name="23453"></a>
<li>class instance creation expressions <a href="15.doc.html#23745">(&#167;15.8.1)</a>
<a name="23469"></a>
<li>array creation expressions <a href="15.doc.html#23605">(&#167;15.9.1)</a>
<a name="23454"></a>
<li>method invocation expressions <a href="15.doc.html#45677">(&#167;15.11.4)</a>
<a name="23491"></a>
<li>array access expressions <a href="15.doc.html#23958">(&#167;15.12.1)</a>
<a name="240795"></a>
<li>assignments involving array components <a href="15.doc.html#5281">(&#167;15.25)</a>
</ul><a name="23302"></a>
<h2>15.7    Primary Expressions</h2>
<a name="36225"></a>
Primary expressions include most of the simplest kinds of expressions, from 
which all others are constructed: literals, field accesses, method invocations, and 
array accesses. A parenthesized expression is also treated syntactically as a primary
expression.
<p><ul><pre>
<i>Primary:<br>
</i>	<i>PrimaryNoNewArray<br>
</i>	<i>ArrayCreationExpression
</i>
<i>PrimaryNoNewArray:<br>
</i>	<i>Literal<br>
</i><code>	this<br>
</code>	<code>( </code><i>Expression</i><code> )<br>
</code>	<i>ClassInstanceCreationExpression<br>
</i>	<i>FieldAccess<br>
</i>	<i>MethodInvocation<br>
</i>	<i>ArrayAccess
</i></pre></ul><a name="236508"></a>
As programming language grammars go, this part of the Java grammar is unusual, in two ways. First, one might expect simple names, such as names of local variables and method parameters, to be primary expressions. For technical reasons, names are lumped together with primary expressions a little later when postfix expressions are introduced <a href="15.doc.html#36254">(&#167;15.13)</a>.<p>
<a name="19353"></a>
The technical reasons have to do with allowing left-to-right parsing of Java programs with only one-token lookahead. Consider the expressions <code>(z[3])</code> and <code>(z[])</code>. The first is a parenthesized array access <a href="15.doc.html#239587">(&#167;15.12)</a> and the second is the start of a cast <a href="15.doc.html#238146">(&#167;15.15)</a>. At the point that the look-ahead symbol is <code>[</code>, a left-to-right parse will have reduced the <code>z</code> to the nonterminal <i>Name</i>. In the context of a cast we prefer not to have to reduce the name to a <i>Primary</i>, but if <i>Name</i> were one of the alternatives for <i>Primary</i>, then we could not tell whether to do the reduction (that is, we could not determine whether the current situation would turn out to be a parenthesized array access or a cast) without looking ahead two tokens, to the token following the <code>[</code>. The Java grammar presented here avoids the problem by keeping <i>Name</i> and <i>Primary</i> separate and allowing either in certain other syntax rules (those for <i>MethodInvocation</i>, <i>ArrayAccess</i>, <i>PostfixExpression</i>, but not for <i>FieldAccess,</i> because this is covered by <i>Name</i>). This strategy effectively defers the question of whether a <i>Name</i> should be treated as a <i>Primary</i> until more context can be examined. (Other problems remain with cast expressions; see <a href="19.doc.html#44559">&#167;19.1.5</a>.)<p>
<a name="36318"></a>
The second unusual feature avoids a potential grammatical ambiguity in the expression:<p>
<pre><a name="36319"></a>new int[3][3]
</pre><a name="36320"></a>
which in Java always means a single creation of a multidimensional array, but 
which, without appropriate grammatical finesse, might also be interpreted as 
meaning the same as:
<p><pre><a name="36321"></a>(new int[3])[3]
</pre><a name="36322"></a>
This ambiguity is eliminated by splitting the expected definition of <i>Primary</i> into 
<i>Primary</i> and <i>PrimaryNoNewArray</i>. (This may be compared to the splitting of 
<i>Statement</i> into <i>Statement</i> and <i>StatementNoShortIf</i> <a href="14.doc.html#32584">(&#167;14.4)</a> to avoid the "dangling 
<code>else</code>" problem.)
<p><a name="224125"></a>
<h3>15.7.1    Literals</h3>
<a name="36407"></a>
A literal <a href="3.doc.html#48272">(&#167;3.10)</a> denotes a fixed, unchanging value.
<p><a name="36387"></a>
The following production from <a href="3.doc.html#48272">&#167;3.10</a> is repeated here for convenience:<p>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -