A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 李文帅 中级黑马   /  2013-10-29 16:40  /  683 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 李文帅 于 2013-10-29 20:43 编辑

这是公开课上付老师写的代码,那天没有听,对以下代码不怎么理解
  1. public class Demo03_StartThread {

  2.         public static void main(String[] args) {
  3.                
  4.                 new Thread(new Runnable() {
  5.                         public void run() {
  6.                                 System.out.println("B");
  7.                         }
  8.                 }) {
  9.                         public void run() {
  10.                                 System.out.println("A");
  11.                         }
  12.                 }.start();
  13.                
  14.                 // 定义了一个Thread类的子类, 重写run()方法, 创建该类对象, 传入了一个Runnable的实现类对象, 调用start()
  15.         }

  16. }
复制代码
执行结果为什么会是“A”,而不是“B”?
希望听了那天课的师兄师姐帮忙解答~

评分

参与人数 1技术分 +1 收起 理由
周志龙 + 1 赞一个!

查看全部评分

7 个回复

倒序浏览
好像是内部类
回复 使用道具 举报
除非是强制调用父类方法,否则只要是被重写的方法都会调用辈分最小的类的啊
回复 使用道具 举报
  1. /*
  2. 查阅API你会发现,Thread类是继承了Runnable接口的:public class Thread implements Runnable
  3. 我们都知道接口中的都是抽象方法,如果类继承了某一个接口,那么该类中的同名函数一定会重写该接口中的方法。

  4. 首先你的程序使用的匿名内部类来书写的,不便于观看。其等价为下面的程序:
  5. */
  6. class runnable implements Runnable
  7. {       
  8.         public void run()
  9.                 {
  10.                         System.out.println("B");
  11.                 }       
  12. }
  13. public class ThreadDemo {

  14.         public static void main(String[] args) {

  15.                         runnable r = new runnable();
  16.                         Thread t = new Thread(r)
  17.                                 {
  18.                                         public void run()
  19.                                         {
  20.                                           System.out.println("A");
  21.                                         }
  22.                                 };               
  23.             t.start();
  24.         }

  25. }
  26. /*
  27. 该程序里出现了两次重写。
  28. 第一次:定义一个新的类继承了Runnable接口,这时用
  29.                 public void run()
  30.                 {
  31.                         System.out.println("B");
  32.                 }
  33.         覆盖了Runnable接口中的run()方法。此时Runnable接口中的run输出的是“B”。
  34. 第二次:建了一个新的线程实体,并指定线程目标为实现了Runnable接口的runnable类的实例r:new Thread(r),
  35. 由于Thread类实现了Runnable接口,所以新的Thread类实体中的run()方法必然要再一次覆盖Runnable接口中的run().
  36. 此时输出“B”的run方法被覆盖。所以输出“A”。

  37. */
复制代码

评分

参与人数 1技术分 +1 收起 理由
黄炳期 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 阿里策 于 2013-10-29 19:45 编辑

    这个我也很疑惑,但是我查找API时,发现Thread类是Runnable接口的子类,其run方法也是实现了Runnable的run方法。所以是不是这样:楼主的new Thread(Runnable r)的参数是一个实现了Runnable接口的匿名内部类,实现了Runnable接口的run方法。而紧接着楼主又创造了一个继承Thread类的匿名内部类,复写了Thread的run方法。这样以来,是不是后一个匿名内部类的run方法,覆盖了前一个匿名内部类的run方法呢???
    这个只是我的猜想,不知道对不对
回复 使用道具 举报 1 0
先分析一下你的这段代码,其实就是new Thread(new Runnable(){}){}
用通俗一点表示就是创建两个类,一个实现Runnable类,一个继承Thread,然后将Runnable的实现类的匿名对象
以参数传递给Thread的子类对象,然后开启线程,因此可以改写代码:
  1. class A implements Runnable{

  2. @Override
  3. public void run() {
  4. System.out.println("A");
  5. }
  6. }

  7. class B extends Thread{
  8. public B(Runnable target) {
  9. super(target);
  10. }

  11. public void run(){
  12. System.out.println("B");
  13. }
  14. }
  15. public class Demo03_StartThread {
  16. public static void main(String[] args) {
  17. A a = new A();
  18. Thread t = new B(a);
  19. t.start();
  20. }
复制代码
因此,答案就出来了,这就是多态的问题,所以打印的是B
没听课,不知道对不对,大家多多指教


评分

参与人数 1技术分 +1 收起 理由
黄炳期 + 1

查看全部评分

回复 使用道具 举报 1 0
new Runnable(){}是以参数的形式传递给Thread对象的,既然new Thread(){run()}有run方法,而且也实现了Runnable接口,他就自己运行了,不论有没有传递new Runnable(){},他都会打印A,除非不在new Thread(){}重写run方法~

如果问题已经解决请及时修改主题为“提问结束”

回复 使用道具 举报
本帖最后由 wenbaoxing 于 2013-10-30 00:37 编辑

这是我的想法,分享交流一下


  1. class Demo03_StartThread {

  2.         public static void main(String[] args) {
  3.                                                
  4.                         // 这个是定义了一个Thread类的匿名子类对象, 重写run()方法, 又调用了父类的含有一个参数的构造方法,子类会覆盖父类的run方法(自己想的不知道对不对)
  5.                         new Thread(new Runnable() {
  6.                                         public void run() {
  7.                                                         System.out.println("B");
  8.                                         }
  9.                                 }) {
  10.                                                 public void run() {
  11.                                                         System.out.println("A");                                                       
  12.                                                 }
  13.                         }.start();

  14.                         /*
  15. 创建线程的第一种方式:继承Thread ,由子类复写run方法。
  16. 步骤:
  17. 1,定义类继承Thread类;
  18. 2,目的是复写run方法,将要让线程运行的代码都存储到run方法中;
  19. 3,通过创建Thread类的子类对象,创建线程对象;
  20. 4,调用线程的start方法,开启线程,并执行run方法。
  21.                         */
  22.                         //这个是通过上面的方法创建线程,这种方法因为继承了Thread类,所以自己有了start方法
  23.                         new A().start();

  24.                         //这个其实也是上面的方法,只不过是Thread的匿名子类,所以也有了start方法
  25.                         new Thread(){
  26.                                 public void run()
  27.                                 {
  28.                                         System.out.println("hello");
  29.                                
  30.                                 }
  31.                         }.start();

  32.                         /*
  33. 创建线程的第二种方式:实现一个接口Runnable。
  34. 步骤:
  35. 1,定义类实现Runnable接口。
  36. 2,覆盖接口中的run方法(用于封装线程要运行的代码)。
  37. 3,通过Thread类创建线程对象;
  38. 4,将实现了Runnable接口的子类对象作为实际参数传递给Thread类中的构造函数。
  39. 为什么要传递呢?因为要让线程对象明确要运行的run方法所属的对象。
  40. 5,调用Thread对象的start方法。开启线程,并运行Runnable接口子类中的run方法。
  41.                         */
  42.                         //通过以上方法创建线程,这种方法为什么一定要放在Thread类中呢?因为A只是实现了Runnable接口,里面没有start方法
  43.                         new Thread (new B()).start();

  44.                         //new B().start();        这样就不行,因为没有start方法

  45.                        
  46.         }

  47. }

  48. class A extends Thread
  49. {
  50.         public void run()
  51.         {
  52.                 System.out.println("A");
  53.         }
  54. }

  55. class B implements Runnable
  56. {
  57.         public void run()
  58.         {
  59.                 System.out.println("B");
  60.        
  61.         }
  62. }
复制代码
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马