I found a strange compiler error when writing the code below. The next
program compiles and runs fine. In fact if I replace the error line
with the null statement it compiles just fine or if I just put the
braces around the error line it compiles. Needless to say, this has
been driving me nuts all morning!
Win XP Pro SP2
JDK 1.6.0-rc build 103
I haven't tried it on an older compiler.
Any ideas?
Thanks,
knute...
import java.util.*;
public class test1 {
public static void main(String[] args) throws Exception {
Hashtable<Integer,String[]> hash =
new Hashtable<Integer,String[]>();
hash.put(1,new String[] {"hello","world"});
hash.put(2,new String[] {"good","bye"});
for (Enumeration<Integer> e=hash.keys(); e.hasMoreElements();)
String[] array = hash.get(e.nextElement()); // <---- error
}
}
C:\com\knutejohnson\redrock\scores>javac test1.java
test1.java:10: '.class' expected
String[] array = hash.get(e.nextElement());
^
test1.java:10: not a statement
String[] array = hash.get(e.nextElement());
^
2 errors
import java.util.*;
public class test1 {
public static void main(String[] args) throws Exception {
Hashtable<Integer,String[]> hash =
new Hashtable<Integer,String[]>();
hash.put(1,new String[] {"hello","world"});
hash.put(2,new String[] {"good","bye"});
for (Enumeration<Integer> e=hash.keys(); e.hasMoreElements();) {
String[] array = hash.get(e.nextElement());
for (int i=0; i<array.length; i++)
System.out.println(array[i]);
}
}
}

Signature
Knute Johnson
email s/nospam/knute/
> In fact if I replace the error line
> with the null statement it compiles just fine or if I just put the
> braces around the error line it compiles.
And your aversion to braces is???
Oliver Wong - 10 Nov 2006 19:47 GMT
>> In fact if I replace the error line with the null statement it compiles
>> just fine or if I just put the braces around the error line it compiles.
>
> And your aversion to braces is???
I think the problem isn't so much "How can I get this to compile?" but
rather "What's wrong with my understanding of the Java language?".
- Oliver
Richard F.L.R.Snashall - 10 Nov 2006 19:53 GMT
>>> In fact if I replace the error line with the null statement it compiles
>>> just fine or if I just put the braces around the error line it compiles.
>> And your aversion to braces is???
>
> I think the problem isn't so much "How can I get this to compile?" but
> rather "What's wrong with my understanding of the Java language?".
So it's as simple as "a declarator block requires braces"?
Oliver Wong - 10 Nov 2006 20:53 GMT
>>>> In fact if I replace the error line with the null statement it compiles
>>>> just fine or if I just put the braces around the error line it
[quoted text clipped - 5 lines]
>
> So it's as simple as "a declarator block requires braces"?
Or that a variable declaration is not considered a statement (something
I didn't know either, until now). I don't think the OP had any doubts that
blocks require braces.
- Oliver
> I found a strange compiler error when writing the code below. The next
> program compiles and runs fine. In fact if I replace the error line
[quoted text clipped - 57 lines]
> Knute Johnson
> email s/nospam/knute/
You can't declare a variable in a one-statement block.
if (true) int something=10; // fails
if (true) { int something=10; } // succeeds.
Also, why not use HashMap?
Map<Integer, String[]> hash = new HashMap<Integer, String[]>();
// Do something with hash
for (Map.Entry<Integer, String[]> entry : hash.entrySet()) {
System.out.print(entry.getKey() + "->{");
for (String string : entry.getValue()) {
System.out.print(string + ", ");
}
System.out.println("}");
}
...
> for (Enumeration<Integer> e=hash.keys(); e.hasMoreElements();)
> String[] array = hash.get(e.nextElement()); // <---- error
...
You are confusing two very different entities, a statement and a
variable declaration.
The for MUST be followed by a statement.
You have a local variable declaration, which is not itself a statement
but can appear in a compound statement, such as a brace-enclosed block.
Incidentally, it seems a bit pointless because you assign to array and
then immediately leave its scope of declaration.
> C:\com\knutejohnson\redrock\scores>javac test1.java
> test1.java:10: '.class' expected
[quoted text clipped - 4 lines]
> ^
> 2 errors
The first error message shows what happened when the compiler tried to
interpret the first few tokens as a statement, not a declaration.
"String[]" is not very likely as the start of a statement, but it could
have been something like "String[].class.notifyAll();". Not finding
".class" killed that idea.
The second message points out that it is not a statement, which is the
real problem.
Patricia
aldeabtalal@hotmail.com - 10 Nov 2006 20:37 GMT
> ...
> > for (Enumeration<Integer> e=hash.keys(); e.hasMoreElements();)
[quoted text clipped - 31 lines]
>
> Patricia
Knute Johnson - 11 Nov 2006 07:14 GMT
> ...
>> for (Enumeration<Integer> e=hash.keys(); e.hasMoreElements();)
[quoted text clipped - 8 lines]
> You have a local variable declaration, which is not itself a statement
> but can appear in a compound statement, such as a brace-enclosed block.
I understand the issue here I just can't find in the JLS where it is not
a statement. In fact, JLS 14.4.4 Execution of Local Variable
Declarations "A local variable declaration statement is an executable
statement.", would seem to say otherwise.
> Incidentally, it seems a bit pointless because you assign to array and
> then immediately leave its scope of declaration.
Yes.
>> C:\com\knutejohnson\redrock\scores>javac test1.java
>> test1.java:10: '.class' expected
[quoted text clipped - 15 lines]
>
> Patricia
I think I found it - 14.4 Local Variable Declaration Statements
"Every local variable declaration statement is immediately contained by
a block. Local variable declaration statements may be intermixed freely
with other kinds of statements in the block."
This is a pretty subtle distinction but I can see the light now.
I can't think of a real situation where you would not have other code
mixed with the local variable declaration. Since you would then need an
enclosing block the error would never occur.
Thanks,

Signature
Knute Johnson
email s/nospam/knute/
Patricia Shanahan - 11 Nov 2006 12:08 GMT
>> ...
>>> for (Enumeration<Integer> e=hash.keys(); e.hasMoreElements();)
[quoted text clipped - 13 lines]
> Declarations "A local variable declaration statement is an executable
> statement.", would seem to say otherwise.
ASCII does not work well for some of this, because it lacks distinct
fonts. Also I should have capitalized "Statement". I meant the syntax
element "Statement", not the English word "statement".
Section 14.5 Statements lists all the productions for the syntax element
Statement. It does not include the syntax element
LocalVariableDeclarationStatement.
The production:
IfThenStatement:
if ( Expression ) Statement
definitely requires a syntax element Statement.
Patricia
Stefan Ram - 11 Nov 2006 16:08 GMT
>ASCII does not work well for some of this, because it lacks
>distinct fonts.
I assume that your intention was not to refer to the encoding
of ASCII but to the format "plain text", which does not allow
markup.
ASCII is an encoding for the ASCII character set.
Your post was encoded in ISO-8859-1, but you are free to
choose UTF-8. Still, you would not have "distinct fonts",
because it still would be "plain text".
>Section 14.5 Statements lists all the productions for the
>syntax element Statement. It does not include the syntax
>element LocalVariableDeclarationStatement.
I like to have this semantic distinction:
A /declaration/ has its effect at compile time,
while a /statement/ has its effect at run time.
Naming a declaration a "statement" would blur this distinction.
Patricia Shanahan - 11 Nov 2006 16:25 GMT
>> ASCII does not work well for some of this, because it lacks
>> distinct fonts.
[quoted text clipped - 7 lines]
> choose UTF-8. Still, you would not have "distinct fonts",
> because it still would be "plain text".
Correct.
>> Section 14.5 Statements lists all the productions for the
>> syntax element Statement. It does not include the syntax
[quoted text clipped - 4 lines]
> while a /statement/ has its effect at run time.
> Naming a declaration a "statement" would blur this distinction.
The distinction is inherently blurred in Java because of initializers.
An initializer has many of the characteristics of an executable
statement. It has to be given a place in the execution sequence, to
define the values of variables it uses and which computations are
affected by its side effects.
Patricia
Knute Johnson - 11 Nov 2006 18:00 GMT
>>> ...
>>>> for (Enumeration<Integer> e=hash.keys(); e.hasMoreElements();)
[quoted text clipped - 30 lines]
>
> Patricia
Patricia:
So do you think this was an arbitrary distinction or is there some
reason that a LocalVariableDeclarationStatement had to be immediately
contained by a block (read that braces). Is it because of the
possibility of multiple execution within the containing block of a 'for'
or other loop?
I found this by accident debugging some code. It would probably never
come up in normal usage. I do find I learn a lot about the subtleties
of the language though when you answer my questions.
Thanks,

Signature
Knute Johnson
email s/nospam/knute/
Patricia Shanahan - 12 Nov 2006 01:23 GMT
...
> So do you think this was an arbitrary distinction or is there some
> reason that a LocalVariableDeclarationStatement had to be immediately
> contained by a block (read that braces). Is it because of the
> possibility of multiple execution within the containing block of a 'for'
> or other loop?
...
No, I think it may be because of the sheer logic of what a declaration is.
My first thought was something like "Well, they could act as though
every statement were in braces of its own, so it can function as block",
but that does not work for declarations:
{
int a = 3;
System.out.println(a);
}
is different from:
{
{int a = 3;}
{System.out.println(a);}
}
The language can't get away with wrapping implicit blocks around
declarations. They have to be written by the programmer, or there is a
risk of messing up scope.
Also, there is a human factors issue. A declaration by itself after an
"if" is at least as likely to be due to missing braces, and the first
line of a longer block, than to be intentional.
Patricia
Knute Johnson - 12 Nov 2006 02:56 GMT
> ...
>> So do you think this was an arbitrary distinction or is there some
[quoted text clipped - 31 lines]
>
> Patricia
Thanks Patricia.

Signature
Knute Johnson
email s/nospam/knute/
Red Orchid - 11 Nov 2006 14:00 GMT
Patricia Shanahan <pats@acm.org> wrote or quoted in
Message-ID: <t755h.4869$l25.4327@newsread4.news.pas.earthlink.net>:
> ...
> > for (Enumeration<Integer> e=hash.keys(); e.hasMoreElements();)
[quoted text clipped - 11 lines]
> Incidentally, it seems a bit pointless because you assign to array and
> then immediately leave its scope of declaration.
#0: "for ( ... ) a declaration statement;"
For a moment, let's consider the above '#0' not to be an error.
Now,
Let's take all possible cases into account.
Case 1)
#1_e:
for (...) int i = 0;
#1_c:
for (...) { int i = 0; }
Both '#1_e' and '#1_c' are useless because 'i' is never
read and '0' is constant.
Case 2)
#2_e:
for (...) int i = parse(...);
#2_c:
for (...) { int i = parse(...); }
Both '#2_e' and '#2_c' are not useless because 'parse(...)'
can change the state of some instances (ex: fields).
Case 3)
#3_e:
for (...) parse(...);
#3_c:
for (...) { parse(...); }
Both '#3_e' and '#3_c' are not useless.
From this point of view, '#*_e' are equivalent to '#*_c' .
But,
'#*_e' are errors and '#*_c' do not.
Is it valid that '#*_c' do not be errors ?
If so, what is the advantage of it ?
"Type name = ... ;" is composed of more than one statements
like a brace-enclosed block.
I think that it is unartificial that a compiler give warnings
about '#*_e', not errors.
Lew - 12 Nov 2006 15:07 GMT
> Patricia Shanahan <pats@acm.org> wrote or quoted in
> Message-ID: <t755h.4869$l25.4327@newsread4.news.pas.earthlink.net>:
[quoted text clipped - 63 lines]
> I think that it is unartificial that a compiler give warnings
> about '#*_e', not errors.
The Java(tm) language is what it is and it ain't what it ain't.
- Lew
Patricia Shanahan - 13 Nov 2006 13:24 GMT
...
> Case 2)
> #2_e:
[quoted text clipped - 5 lines]
> Both '#2_e' and '#2_c' are not useless because 'parse(...)'
> can change the state of some instances (ex: fields).
However, making them variable declarations rather than expression
statements is useless. All side effects of 'parse(...)' happen for
for (...)
parse(...);
Patricia