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循环里加个大括号就不会报错了,问题是,for循环中如果只有一句话,大括号不是可以省略的么?
public static void main(String[] args) {
for (int i = 0; i < 100; i++)
new Creature();//notice
System.out.println(Creature.numCreated());
}
}
class Creature {
private static long numCreated = 0; public Creature() {
numCreated++;
}
public static long numCreated() {
return numCreated;
}
}
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 类型的计数器。
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语句不支持变量的声明
Creature creature = new Creature();
这for循环里面creature出现重名
如果在for循环里加个大括号,那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;
}
}你自己对照这看吧``你错了很多很多!
2、调用方法的时候你使用的是类名而不是对象名!
for的循环体在只有一条语句的时候,是可以省略大括号的。
Creature creature = new Creature();
Creature creature = new Creature();
Creature creature = new Creature();
Creature creature = new Creature();
Creature creature = new Creature();
....100个.
Creature creature = new Creature();
}那么把你的代码与这里的相比一下是不是明白了呢?重复声明creature 肯定是不行的,那么实际上楼上已经有了解决办法,我补全一点:
改成:
这里解释一下:实际楼主的本意是要在这里调用构造方法,因为调用了构造方法才进行了numCreated++操作
有两种改法楼上都已有:
方法一:for (int i = 0; i < 100; i++)
new Creature();
System.out.println(Creature.numCreated()); }方法二:Creature creature ;
for (int i = 0; i < 100; i++){
creature = new Creature();
}
System.out.println(Creature.numCreated()); }至于10、11、12楼所说也没错,不过提出的并不是问题关键所在,调用静态方法用类名或实例名都是可以的,只不过静态方法不属于某一个对象所有就是了如public class Test {
public static void main(String[] args) {
Creature c1 = new Creature();
Creature c2 = new Creature();
System.out.println(c1.numCreated());
System.out.println(c2.numCreated());
System.out.println(Creature.numCreated()); }
}class Creature {
private static long numCreated = 0; public Creature() {
numCreated++;
} public static long numCreated() {
return numCreated;
}
}上面三种方式都是可以的,输出结果都为2.
这里关键要理解static方法不属于任何对象的!即没有对象的时候也是可以存在的。
public static void main(String[] args) { Creature creature = new Creature();
for (int i = 0; i < 100; i++) {
System.out.println(Creature.numCreated() ); }
}
}
class Creature {
private static long numCreated = 0; public Creature() {
numCreated++;
}
public static long numCreated() {
return numCreated;
}
}如果这样改了,可以编译,但是结果全是1
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;
}
}看了一些资料,听说是这样的因为for循环没加大括号,for的作用域就一句,所以java认为这时候声明一个局部变量没必要,因为永远有不会有人用到它,加了大括号了就有可能被使用到所以语法上就允许它这样用了,至于你用不用java也猜不到所以它就不管了。
PS:据说 for循环里声明变量比较占内存,没必要的情况下在for循环外声明。上面这段程序建议修改成:
public class Creator {
public static void main(String[] args) {
for (int i = 0; i < 100; i++)
new Creature();
System.out.println(Creature.numCreated());
}
}
class Creature {
private static long numCreated = 0; public Creature() {
numCreated++;
}
public static long numCreated() {
return numCreated;
}
}
后面加个“;”,改成for (int i = 0; i < 100; i++);
就行了,呵呵!
for (int i = 0; i < 100; i++)
Creature creature = new Creature();
System.out.println(Creature.numCreated());上面的效果同下for (int i = 0; i < 100; i++){
Creature creature = new Creature();
}
System.out.println(Creature.numCreated());你去看下变量的作用域
就这样养成了这种习惯,难怪没遇到这种情况。