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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 芦子骐 中级黑马   /  2013-3-28 23:16  /  1328 人查看  /  9 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 芦子骐 于 2013-3-29 12:01 编辑

问题在后面的put类中,其他的只是怕各位单看问题代码不方便

//主函数
class test
{
        public static void main(String[] args)
        {
                Bank b = new Bank();
                new Thread(new out(b)).start();
                new Thread(new put(b)).start();
        }
}
//Bank类中有name和mony属性以及对应的set get方法
class Bank
{
        String name;
        int mony;
        public synchronized void setBank(String name,int mony)
        {
                this.name = name;
                this.mony = mony;
        }
        public synchronized void getBank()
        {
                //Sop.sop()是我定义的System.out.println()类,看过毕老师视频的同学,你们懂得……
                Sop.sop(name+"........"+mony);               
        }
}
// out类主要是输出Bank类中的name 和 mony
class out implements Runnable
{
        Bank b;
        out(Bank b)
        {
                this.b = b;
        }
        public void run()
        {
                while(true)
                {
                        b.getBank();
                }
               
        }
}
//put 类 这个是问题的关键
class put implements Runnable
{
        Bank b;
        put(Bank b)
        {
                this.b = b;
        }
        public void run()
        {
                // 这里: 我想每次运行的时候判断,如果Bank的name是ZhangSan 那就将LiSi 赋给他
                //但是输入结果一直是null..........0,求解呀~~这个判断语句有错么???
                while(true)
                {
                        if(b.name.equals("ZhangSan"))
                        {
                                b.setBank("LiSi",999);
                        }
                        else
                        {
                                b.setBank("ZhangSan",100);
                        }
                                
                }

        }
}

点评

如果问题解决了,请将问题改为已解决,谢谢  发表于 2013-3-29 07:46

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

9 个回复

倒序浏览
刚才我试了一下,这样写就可以,一会儿输出zhangsan  100  一会儿输出LiSi  999   
                while(true)
                {
                        if(b.mony == 100)
                        {
                                b.setBank("LiSi",999);
                        }
                        else
                        {
                                b.setBank("ZhangSan",100);
                        }
回复 使用道具 举报
哈哈  子琪你中邪了  我也在研究呢  希望能来个大牛帮帮我们吧
回复 使用道具 举报
本帖最后由 张豪杰 于 2013-3-28 23:48 编辑

if(b.name.equals("ZhangSan")
这里改成if("zhansan".equals(b.name))试试
按你原来的方式写,可能会出现b.name=null的情况-。-
回复 使用道具 举报
废了将近半小时,终于解决了,嘿嘿
先看MyEclipase给出的运行结果,高级IDE就是好啊。
null........0Exception in thread "Thread-1" java.lang.NullPointerException
at com.itheima(这是我的包,不用管它).put.run(TestMan.java:60)
at java.lang.Thread.run(Thread.java:619)
很明显,你的第二个线程出现了异常,空指针异常,但是线程一还在 执行,所以一堆的null......0


因为你的写法:
  if(b.name.equals("ZhangSan")
                        {
                                b.setBank("LiSi",999);
                        }
其中b.name在前,但是你创建的b是无参的,所以堆内存中b的name默认是null,这个明白吧?因为b.name是String类型的,而String是引用类型的,故堆内存中默认初始化是null。若这里不明白,先跳过,知道这个的存在就好。
所以你的if括号内是null.equals("zhangsan"),这是会引发空指针(NullPointerException)异常的。
所以此时你的第二个线程(Thread-1,线程的默认命名,是从Thread-0开始的),很不幸的挂掉了。
再看你的main方法,就能明白为什么一直是null......0了。
到此搞定你的问题。


接下来给你解释下空指针异常(NullPointerException):
为什么你的
b.mony == 100可以通过呢?因为mony是基本类型,默认值为0,且==不会引发空指针的。
但是你想过没有,为什么.equals()会引发空指针呢?好好看看下面几句话,你会有所收获的,相信我!
注意:equals()是一个方法,它是String类的一个方法,故肯定被String类型的对象所调用,你的name的具体值对象很明显就是一个String类型的对象(如果name不为null的话),但是如果你没有给name赋值,name也有值,是null,不是String类型的,所以null是不能调用equals()方法的,这就是为什么你的写法会出现空指针异常的原因了,以后可得记住了!不要把对象的属性写在前面,这样的代码不健壮!
去看看String类源码,就会彻底明白NullPointerException这个异常啦!
哇,两点半了,睡觉去啦,祝你有所进步,不会的敬请追问~~

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 perfect

查看全部评分

回复 使用道具 举报
HM马明宇 发表于 2013-3-29 02:31
废了将近半小时,终于解决了,嘿嘿
先看MyEclipase给出的运行结果,高级IDE就是好啊。
null........0Except ...

哈哈!谢谢你了!!回答的太详细了!!我在定义属性的时候给name先赋值成ZhangSan这样果然可以了~~~
其实刚开始我是这么想的,既然是空,那肯定就不等于张三了,肯定会去执行李四那句的,但是我还是对指针的概念不是太清晰,不知道空和字符串是不能比较的~嘿嘿~多谢大牛指导!!!!!
3点啦……嘿嘿……我也去睡觉了……
回复 使用道具 举报
蔡陶军 发表于 2013-3-28 23:35
哈哈  子琪你中邪了  我也在研究呢  希望能来个大牛帮帮我们吧

哈哈~缘分呐~~
回复 使用道具 举报
不太明白撸主的意思,是想交替打印?

你没有给Bank赋值,先执行put的时候当然是总是执行打印没有被赋值的Bank的数据


下面是我改了之后的代码
  1. package snippet;

  2. public class Test {
  3.        
  4.         public static void main(String[] args) {
  5.                                
  6.                 Bank b = new Bank("ZhangSan", 100);
  7.                
  8.                 new Thread(new put(b)).start();
  9.                 new Thread(new out(b)).start();
  10.         }
  11. }

  12. // Bank类中有name和mony属性以及对应的set get方法
  13. class Bank {
  14.        
  15.         boolean flag = true;
  16.        
  17.         String name;
  18.         int mony;

  19.         public Bank(String name, int mony) {
  20.                 this.name = name;
  21.                 this.mony = mony;
  22.         }

  23.         public void setBank(String name, int mony) {
  24.                 this.name = name;
  25.                 this.mony = mony;
  26.         }

  27.         public void getBank() {
  28.                 System.out.println(name + "........" + mony);
  29.         }
  30. }


  31. //put 类 这个是问题的关键
  32. class put implements Runnable {
  33.        
  34.         Bank b;

  35.         put(Bank b) {
  36.                 this.b = b;
  37.         }

  38.         public void run() {
  39.                 // 这里: 我想每次运行的时候判断,如果Bank的name是ZhangSan 那就将LiSi 赋给他
  40.                 // 但是输入结果一直是null..........0,求解呀~~这个判断语句有错么???
  41.                
  42.                 synchronized (b.getClass()) {
  43.                        
  44.                         while (b.flag) {
  45.                                 b.getClass().notify();
  46.                                 if (b.name.equals("ZhangSan")) {
  47.                                         b.setBank("LiSi", 999);
  48.                                 } else {
  49.                                         b.setBank("ZhangSan", 100);
  50.                                 }
  51.                                 b.flag = false;
  52.                                 try {
  53.                                         b.getClass().wait();
  54.                                 } catch (InterruptedException e) {
  55.                                         e.printStackTrace();
  56.                                 }
  57.                         }
  58.                        
  59.                        
  60.                 }
  61.                
  62.                
  63.         }
  64. }



  65. // out类主要是输出Bank类中的name 和 mony
  66. class out implements Runnable {
  67.        
  68.         Bank b;

  69.         out(Bank b) {
  70.                 this.b = b;
  71.         }

  72.         public void run() {
  73.                
  74.                 synchronized (b.getClass()) {
  75.                        
  76.                         while (!b.flag) {
  77.                                 b.getClass().notify();
  78.                                 b.getBank();
  79.                                 b.flag = true;
  80.                                 try {
  81.                                         b.getClass().wait();
  82.                                 } catch (InterruptedException e) {
  83.                                         e.printStackTrace();
  84.                                 }
  85.                         }
  86.                
  87.                 }
  88.                
  89.                
  90.         }
  91. }
复制代码



回复 使用道具 举报
芦子骐 发表于 2013-3-29 03:05
哈哈!谢谢你了!!回答的太详细了!!我在定义属性的时候给name先赋值成ZhangSan这样果然可以了~~~
其实 ...

null这个东东是一个值,所以没有引用,注意啦:这里的引用就类似于指针,c里面是这个概念,它既然不是String类型的变量,怎么能去调用equals()方法呢?
回复 使用道具 举报
嘿嘿,哥们儿的头像表情生动,赞一个!!!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马