Runnable是一个接口,不能直接new Runnable()你可在内部用new Thread(){
}Thread也是实现了Runnable接口的。实现了Runnable接口,声明时应该用
Runnable mt1 = new MyThread1()
}Thread也是实现了Runnable接口的。实现了Runnable接口,声明时应该用
Runnable mt1 = new MyThread1()
调试欢乐多
第一:你写的不叫内部类
第二:Runnable接口你如何直接new ?
可以这样:
<<
new Thread(new MyThread1()).start();
>>
我写的是一个匿名内部类,是可以通过new Runnable()来实现Runnable接口的,请你详细的说一下,多谢
class MyThread1 implements Runnable{
Thread th = new Thread(this);
public void run(){
for (int i = 0; i < 10; i++){
System.out.println(i);
}
}
是正常的,能打印出0到9。关键是
class MyThread2{
Thread th = new Thread(this.ra);
Runnable ra = new Runnable(){
public void run(){
for (char ch = 65; ch < 70; ch++){
System.out.println(ch);
}
}
};
}有问题,固然
Runnable ra = new Runnable(){
public void run(){
for (char ch = 65; ch < 70; ch++){
System.out.println(ch);
}
}
};不对,但jbuilder9确没认识错误和警告信息提示,很奇怪。
明明new Runnable() 有问题。
楼主,你的顺序有问题,你这改再试试:
在MyThread2中,把Thread th = new Thread(this.ra);
放到Runnable ra =...的后面。
<<
Runnable r = new Runnable() {
public void run() {}
}
>>
这样做是没有任何问题的。:)
jbuilder9 是不会出编译错误的,因为这句话是合法的,它是声明了一个匿名内部类,这个内部类实现了Runnable接口。
public static void main(String[] args){
MyThread1 mt1 = new MyThread1();
MyThread2 mt2 = new MyThread2();
mt2.th.start();
mt1.th.start();
}
}
class MyThread1 implements Runnable{
Thread th = new Thread(this);
public void run(){
for (int i = 0; i < 10; i++){
System.out.println(i);
}
}
}
class MyThread2{
//Thread th = new Thread(this.ra);
Runnable ra = new Runnable(){
public void run(){
for (char ch = 65; ch < 70; ch++){
System.out.println(ch);
}
}
};
Thread th = new Thread(this.ra);}
xiaohaiz(老土进城,两眼通红) 还是慧眼。
你的这个建议可以,多谢指教,能不能说说原因呢
<< (A)
public class A {
Thread th = new Thread(ra);
Runnable ra = new Runnable() {
public void run() {}
};
}
>>
上面有问题吗?有:编译就会出现“ illegal forward reference”错误,因为你的初始化顺序有问题。但是楼主偏偏在new Thread(ra)的地方写成了new Thread(this.ra),变成了这样:
<< (B)
public class A {
Thread th = new Thread(this.ra); // -- NOTICE HERE.
Runnable ra = new Runnable() {
public void run() {}
};
}
>>
俺们现在来看看这样的初始化顺序,实际上上面的顺序可以演化为这样:
<< (C)
public class A {
Thread th;
Runnable ra;
{
th = new Thread(ra);
ra = new Runnable() {
public void run();
};
}
}
>>
(B)和(C)的字节码是一样的。我们把字节码反编译也放在下面:
<<
public A();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: new #2; //class Thread
8: dup
9: aload_0
10: getfield #3; //Field ra:Ljava/lang/Runnable;
13: invokespecial #4; //Method java/lang/Thread."<init>":(Ljava/lang/Runna
ble;)V
16: putfield #5; //Field th:Ljava/lang/Thread;
19: aload_0
20: new #6; //class A$1
23: dup
24: aload_0
25: invokespecial #7; //Method A$1."<init>":(LA;)V
28: putfield #3; //Field ra:Ljava/lang/Runnable;
31: return
}
>>
10:getfield取到的是null。呵呵。走到这里,大家也应该看明白了吧?关键看(C),实际上你在构造
Thread th = new Thread(ra)的时候,ra现在还是null,所以你构造了一个new Thread(null),这就是为什么你编译没有问题但是运行结果有问题。如果俺们把顺序交换,变成这样:
<< (D)
public class A {
Runnable ra = new Runnable() {
public void run() {}
};
Thread th = new Thread(ra);}
>>
这样在初始化的时候就变成这样:
<< (E)
public class A {
Runnable ra;
Thread th;
{
ra = new Runnable() {public void run(){}};
th = new Thread(ra);
}
}
>>
这样自然就没有问题了。(E)的字节码如下:
<<
public A();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: new #2; //class A$1
8: dup
9: aload_0
10: invokespecial #3; //Method A$1."<init>":(LA;)V
13: putfield #4; //Field ra:Ljava/lang/Runnable;
16: aload_0
17: new #5; //class Thread
20: dup
21: aload_0
22: getfield #4; //Field ra:Ljava/lang/Runnable;
25: invokespecial #6; //Method java/lang/Thread."<init>":(Ljava/lang/Runna
ble;)V
28: putfield #7; //Field th:Ljava/lang/Thread;
31: return
}
>>
22:getfield取到的是Field ra.