为什么这段代码编译时会报错???Java codepublic class Creator {public static void main(String[] args)
为什么这段代码编译时会报错???
Java code
public class Creator { public static void main(String[] args) { for (int i = 0; i < 100; i++) Creature creature = new Creature(); System.out.println(Creature.numCreated()); }}class Creature { private static long numCreated = 0; public Creature() { numCreated++; } public static long numCreated() { return numCreated; }}
2个错误分别是: 2 errors found: File: C:\Documents and Settings\Admin\Desktop\Creator.java [line: 4] Error: C:\Documents and Settings\Admin\Desktop\Creator.java:4: not a statement File: C:\Documents and Settings\Admin\Desktop\Creator.java [line: 4] Error: C:\Documents and Settings\Admin\Desktop\Creator.java:4: ';' expected
[解决办法] 应该是不加大括号的时候for语句不支持变量的声明,你可以把Creature creature放到for上面去,或者像1楼的那样 [解决办法] 某些时候,对于一个类来说,跟踪其创建出来的实例个数会非常用有,其典型实现是通过让它的构造器递增一个私有静态域来完成的。在下面的程序中,Creature 类展示了这种技巧,而 Creator 类对其进行了操练,将打印出已经创建的 Creature 实例的数量。那么,这个程序会打印出什么呢? public class Creator { public static void main(String[] args) { for (int i = 0; i < 100; i++) Creature creature = new Creature(); System.out.println(Creature.numCreated()); } } class Creature { private static long numCreated = 0; public Creature() { numCreated++; } public static long numCreated() { return numCreated; } } 这是一个捉弄人的问题。该程序看起来似乎应该打印 100,但是它没有打印任何东西,因为它根本就不能编译。如果你尝试着去编译它,你就会发现编译器的诊断信息基本没什么用处。下面就是 javac 打印的东西: Creator.java:4: not a statement Creature creature = new Creature(); ^ Creator.java:4: '';'' expected Creature creature = new Creature(); ^ 一个本地变量声明看起来像是一条语句,但是从技术上说,它不是;它应该是一个本地变量声明语句(local variable declaration statement)[JLS 14.4]。Java 语言规范不允许一个本地变量声明语句作为一条语句在 for、while 或 do 循环中重复执行[JLS 14.12-14]。一个本地变量声明作为一条语句只能直接出现在一个语句块中。(一个语句块是由一对花括号以及包含在这对花括展中的语句和声明构成的。)有两种方式可以订正这个问题。最显而易见的方式是将这个声明至于一个语句块 中: for (int i = 0; i < 100; i++) { Creature creature = new Creature(); } 然而,请注意,该程序没有使用本地变量 creature。因此,将该声明用一个无 任何修饰的构造器调用来替代将更具实际意义, 这样可以强调对新创建对象的引 用正在被丢弃 for (int i = 0; i < 100; i++) new Creature(); 无论我们做出了上面的哪种修改,该程序都将打印出我们所期望的 100。 请注意,用于跟踪 Creature 实例个数的变量(numCreated)是 long 类型而不是 int 类型的。 我们很容易想象到, 一个程序创建出的某个类的实例可能会多余 int 数值的最大值,但是它不会多于 long 数值的最大值。 int 数值的最大值是 231-1,即大约 2.1×109,而 long 数值的最大值是 263-1, 即大约 9.2×1018。当前,每秒钟创建 108 个对象是可能的,这意味着一个程序 在 long 类型的对象计数器溢出之前,不得不运行大约三千年。即使是面对硬件 速度的提升,long 类型的对象计数器也应该足以应付可预见的未来。 还要注意的是,本谜题中的创建计数策略并不是线程安全的。如果多个线程可以 并行地创建对象,那么递增计数器的代码和读取计数器的代码都应该被同步: // Thread-safe creation counter class Creature { private static long numCreated; public Creature() { synchronized (Creature.class) { numCreated++; } } public static synchronized long numCreated() { return numCreated; } } 或者,如果你使用的是 5.0 或更新的版本,你可以使用一个 AtomicLong 实例, 它在面临并发时可以绕过对同步的需求。 // Thread-safe creation counter using AtomicLong; import java.util.concurrent.atomic.AtomicLong; class Creature {
private static AtomicLong numCreated = new AtomicLong(); public Creature() { numCreated.incrementAndGet(); }
public static long numCreated() {
return numCreated.get(); } } 请注意,把 numCreated 声明为瞬时的是不足以解决问题的,因为 volatile 修饰 符可以保证其他线程将看到最近赋予该域的值, 但是它不能进行原子性的递增操 作。 总之,一个本地变量声明不能被用作 for、while 或 do 循环中的重复执行语句, 它作为一条语句只能出现在一个语句块中。另外,在使用一个变量来对实例的创 建进行计数时,要使用 long 类型而不是 int 类型的变量,以防止溢出。最后, 如果你打算在多线程中创建实例,要么将对实例计数器的访问进行同步,要么使 用一个 AtomicLong 类型的计数器。 [解决办法] //不加大括号的时候for语句不支持变量的声明 public class Creator { public static void main(String[] args) { Creature creature; for (int i = 0; i < 100; i++) creature = new Creature(); System.out.println(Creature.numCreated());
} } class Creature { private static long numCreated = 0;
public Creature() { numCreated++; } public static long numCreated() { return numCreated; } } [解决办法] 记住这一句就行了。 不加大括号的时候for语句不支持变量的声明 [解决办法] 不加大括号的时候for语句不支持变量的声明 [解决办法] 很简单的问题,变量重复声明。
for后面不加大括号,就没有构成子作用域(Sub Scope),这样Creature creature这个变量是属于for上层作用域的,这就相当于在同一个作用域中反复声明同一个变量,当然是不能编译的。 [解决办法] for (int i = 0; i < 100; i++) Creature creature = new Creature(); 这for循环里面creature出现重名 如果在for循环里加个大括号,那creature就属于局部变量,作用域只在大括号里,出了大括号(再循环一次)就被垃圾回收了,就不会出现重名的情况。
^_^个人见解 [解决办法]
[解决办法]
Java code
public class Creator { public static void main(String[] args) { for (int i = 0; i < 100; i++) Creature creature = new Creature(); System.out.println(Creature.numCreated()); }}class Creature { private static long numCreated = 0; public Creature() { numCreated++; } public static long numCreated() { return numCreated; }}