java对线程数组用for(Thread t : threads)遍历并创建实例后无法通过下标访问

public class MyThreadB extends Thread{
    private int i;
    public MyThreadB(){}
    public MyThreadB(String name){
        super();
        this.setName(name);
    }
    @Override
    synchronized public void run(){
        i--;
        System.out.println(currentThread().getName() + " : " + i);
    }

    public static void main(String[] args) {

        //多线程共享实例变量demo
        MyThread thread = new MyThread(5);
        Thread[] threads = new Thread[5];
        char a = 97;
        // 让threads数组中的五个thread共享传入的myThread中的实例变量
        for(int i = 0; i < 5; i++){
            String s = String.valueOf(a++);
            //调用Thread类的Thread(Runnable target, String name)构造函数
            threads[i] = new Thread(thread, s);

            threads[i].run();

        }
        System.out.println(threads[1].isAlive());
    }
}

完整代码如上,问题出在截图所示的部分:

按照如上的代码,运行到第43行的sout输出语句就回抛出空指针异常,提示threads[1]为空(不光是下标为1的为空,所有都为空)

不管把第43行的sout语句放到39行还是41行、也不管是使用t.start()还是t.run(),sout语句都抛出空指针异常。当然,在39行或41行加上

System.out.println(t.isAlive());

是可以正常运行的。

尝试了一下通过下标遍历,如下图。则第43行正常运行不会出现空指针异常

 

不知道为何会是这种情况——通过for( : )语句遍历Thread对象创建实例会出现通过下标访问则抛出空指针异常的问题

 

希望有大佬帮忙解答

for each循环等价于使用迭代器的普通for循环,其中的t是每次循环创建的内部变量,并把迭代器的next()赋值给该变量,所以无法通过赋值对原来的数组进行改变。

提问中的行数是以截图为准的,粘贴的代码删去了一些不必要的注释信息所以行号偏小