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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 周学彬 中级黑马   /  2013-10-20 13:18  /  1502 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 周学彬 于 2013-10-20 17:01 编辑
  1. public class ThreadDemo {
  2.         public static void main(String[] args) {
  3.                 Test t_1 = new Test("one");
  4.                 Test t_2 = new Test("two");
  5.                 t_1.start();
  6.                 t_2.start();
  7.         }
  8. }

  9. class Test extends Thread {
  10.         private String name;
  11.         Test (String name) {
  12.                 this.name = name;
  13.         }
  14.         public void run() {
  15.                 System.out.println(this.getName());
  16.                 for (int i = 0; i < 60; i++) {
  17.                         System.out.println(Thread.currentThread().getName() + "...run" + " " + i + " times.");
  18.                 }
  19.         }
  20. }
复制代码
如上段代码所示,创建一个Test子类继承Thread,并有自己的构造方法。构造方法里有要传递的参数,参数即为该线程的名称
按理说,Test类创建对象并启动时,线程通过getName()方法获取的应该是往构造函数里面传递的name参数,但是打印出来的结果却是默认的Thread-0
视频里是用super(name)的方法直接继承父类的构造方法,这个可以理解。但是不使用super方法应该也能达到同样的目的啊,为什么却是默认的线程名称呢?
求解。

评分

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

查看全部评分

6 个回复

倒序浏览
  1. public class ThreadDemo {
  2.         public static void main(String[] args) {
  3.                 Thread t_1 = new Test("one");
  4.                 Thread t_2 = new Test("two");
  5.                 t_1.start();
  6.                 t_2.start();
  7.         }
  8. }

  9. class Test extends Thread {
  10.         private String name;
  11.         Test (String name) {
  12.                 super.setName(name);
  13.         }
  14.         public void run() {
  15.                 System.out.println(this.getName());
  16.                 for (int i = 0; i < 60; i++) {
  17.                         System.out.println(Thread.currentThread().getName() + "...run" + " " + i + " times.");
  18.                 }
  19.         }
  20. }
复制代码
你继承创建的是自己name…… 有没给父类的构造传什么
回复 使用道具 举报
我把打印语句的Thread.currentThread().getName()换成this.getName()结果还是默认的Thread-0
回复 使用道具 举报
本帖最后由 卜弦 于 2013-10-20 14:22 编辑

  1. <P>public class ThreadDemo {
  2.         public static void main(String[] args) {
  3.                
  4.                  Test t_1 = new Test("one");
  5.                 Test t_2 = new Test("two");
  6.                 t_1.start();
  7.                 t_2.start();
  8.         }
  9. }

  10. class Test extends Thread {
  11.       
  12.                
  13.                 private String name;   
  14.                 Test (String name) {
  15.                 this.name = name;
  16.                                 /*第二种方式
  17.                                         super(name);
  18.                                 */
  19.         }
  20.                
  21.         public void run() {
  22.                 System.out.println(this.getName());
  23.                 for (int i = 0; i < 60; i++) {

  24.      /*第一种方式
  25.         System.out.println(name + "...run" + " " + i + " times.");
  26.         System.out.println(Thread.currentThread().getName() + "...run" + " " + i + " times.");
  27.         */
  28.          System.out.println(Thread.currentThread().getName() + "...run" + " " + i + " times.");
  29.                 }
  30.         }
  31. }
  32. </P>
复制代码
/*
第一种方式:通过构造函数传入一个字符串,在输出时将字符串加在一起输出。这种方式并不是真的给线程命名,
                        只是给主观的给线程一个标识,实际上线程名称还是默认的Thread-0...等。

第二种方式:因为线程在构造时可以直接传入名称,同样通过构造函数传入字符串,但是在构造函数里,要调用父类Thread
                        的构造方法才行。子类调用父类构造函数通过super();因为是调用带参数的构造函数所以采用super(name);

第三种方式:通过setName方法。在主函数里通过以下四句话
                                Test t_1 = new Test();
                                Test t_2 = new Test();
                                t_1.setName("one");
                                t_2.setName("two");
                        这时记得把下面的话注释掉,因为通过这种方法,就没必要再用到构造函数了。
/*               
                private String name;
                Test (String name)
                        {
                             this.name = name;                                
                        }
               
*/

评分

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

查看全部评分

回复 使用道具 举报
Test继承自Thread,可是在Test构造函数中,你没有显示调用Thread有参数构造函数,这样在构造子类对象的时候,系统将会首先调用Thread的无参构造函数,
  1. public Thread() {
  2.         init(null, null, "Thread-" + nextThreadNum(), 0);
  3.     }
复制代码
在init函数中,"Thread-" + nextThreadNum()赋值给name属性,所以调用getName()函数时返回Thread-0
  1. public final String getName() {
  2.         return String.valueOf(name);
  3.     }
复制代码
回复 使用道具 举报
本帖最后由 我能学编程吗 于 2013-10-20 14:58 编辑

发表个人观点:
我觉得了解问题要本质,我个人认为是楼主没有理解好继承的相关知识点,运行如下代码:
  1. class Demo {

  2.         public static void main(String[] args) {
  3.                 Zi zi = new Zi();
  4.                 System.out.println(zi.getName());  // 输出结果是:   Fu
  5.         }
  6. }

  7. class Fu {
  8.         public String name = "Fu";
  9.         
  10.         public String getName() {
  11.                 return name;
  12.         }
  13. }

  14. class Zi extends Fu {
  15.         public String name = "Zi";
  16. }
复制代码
从上面代码的输出结果可知,子类调用父类的getName方法,访问的是父类的name,而不是子类的name,所以你应该知道问题所在了吧!
你想调用子类的getName来获取子类的name的话,你可以覆盖 父类的getName方法,这样获取name就是子类的name了,如下:
  1. class Zi extends Fu {
  2.         public String name = "Zi";
  3.         
  4.         public String getName() {
  5.                 return name;
  6.         }
  7. }
复制代码
但这个覆盖 对于你的Thread的子类不管用,为什么呢?查看Thread的getName方法的源代码如下:
  1. public final String getName() {
  2.             return String.valueOf(name);
  3.     }
复制代码
我们看到 Thread的getName方法是final的,也就是说是最终的,是不能覆盖的不知道我的这个答案是否比上面的要正确,给点技术分吧!


回复 使用道具 举报
多谢楼上各位,我看了源码,差不多都明白了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马