日期:2014-05-20  浏览次数:20820 次

我的一小段程序,一运行就空指针错误,为什么
我模仿网上的多线程不同写了一个自动提款机的小程序,一运行就扔空指针错误。我eclipse提示是Thread.start()方法错误了,可是我看不出这里怎么就空指针了,我明明创建了对象啊。
Java code

public class my{
    public static void main(String[] args){
        ATM[] pArr=new ATM[100];
        for(int i=0;i<pArr.length;++i){
            pArr[i].start();
        }
    }
    static class Account{
        int m_amount;
        String m_name;
        Account(int m,String name){
            m_amount=m;
            m_name  =name;
        }
        void Deposit(int m){
            try{
                int a=m_amount;
                a+=m;
                Thread.sleep(100);
                m_amount=a;
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
        void WithDraw(int m){
            try{
                int a=m_amount;
                a-=m;
                Thread.sleep(100);
                m_amount=a;
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }
    static class ATM extends Thread{
        static Account m_acc=new RevertList.Account(10,"self");
        public void run(){
            m_acc.Deposit(1);
            m_acc.WithDraw(1);
        }
    }
}



------解决方案--------------------
创建了数组,数组里的对象默认是null,需要初始化!
------解决方案--------------------
如果是基本类型的数组的话,系统会分配一个默认初始值,比如int数组就是0
但如果是引用类型的话,分配了内存但没有初始化,即null,因而提示空指针异常
------解决方案--------------------
对象数组为空
可以再for循环里创建多个线程

------解决方案--------------------
初学者常见错误:

你只是创建了数组,但没有创建数组中的元素:
for(int i=0;i<pArr.length;++i){
pArr[i] = new ATM(); // 这才真的创建了数组中的元素所引用的对象。
pArr[i].start();
}

------解决方案--------------------
探讨

初学者常见错误:

你只是创建了数组,但没有创建数组中的元素:
for(int i=0;i<pArr.length;++i){
pArr[i] = new ATM(); // 这才真的创建了数组中的元素所引用的对象。
pArr[i].start();
}

------解决方案--------------------
ATM[] pArr=new ATM[100];
你只是创建了数组,但没有创建数组中的元素所以是个长度为100的空数组
------解决方案--------------------
ATM[] pArr=new ATM[]{new ATM()};
------解决方案--------------------
探讨
引用:

引用:
如何又能指定大小,又能在创建数组的时候指定new ATM()呢?


不行的。按照我 4 楼的做法来吧。


我按照你的说法来做了,不过发现,每次运行的结果都是"正确的"。这很奇怪,按照网上的说法,这个程序我既然没有对Deposit和Withdraw来加锁,那么应该运行的结果不确定才对啊。

------解决方案--------------------
探讨

初学者常见错误:

你只是创建了数组,但没有创建数组中的元素:
for(int i=0;i<pArr.length;++i){
pArr[i] = new ATM(); // 这才真的创建了数组中的元素所引用的对象。
pArr[i].start();
}

------解决方案--------------------
与其在这里告诉LZ是什么引起了空指针异常,还不如告诉LZ怎么用Debug调试。你这次知道原因了,下次一粗心,不会又来这里发个帖子吧。
Debug断点到发生错误的地方,然后看变量,(x)=Variables窗口你调试的时候看过多少次?出了问题就一头裁进代码里看,睁大了眼睛,自信满满的以为看一眼就能知道哪里出错,总有一天你会感觉到头昏脑胀的。
------解决方案--------------------
关于第10楼----
难道你认为'Final amount=10'的结果是正确的? 它可以是这样的情况
1. 所有ATM的线程都还没跑到run里面(毕竟需要时间),就输出了
2. 所有ATM的线程都还没跑到给m_amount赋值那里,就输出了
3. 有一个ATM的线程'刚好'跑完一个run而其它线程处于1 或 2的情况,就输出了.
---
要重现错误,只要在Debug下控制不同线程在run里一步一步跑上去就很容易看到了.
------解决方案--------------------