NullPointerException异常的二维数组 [英] NullPointerException in 2D array

查看:152
本文介绍了NullPointerException异常的二维数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了这个code(自包含),它抛出了我的困惑NPE。它涉及在模型中使用对象的二维数组。在对象初始化并设置模型。当他们需要在模型外,在code调用 model.getRays()。在这一点上code遍历二维数组和放大器;日志的每个对象,因为..区区2-3线code来电之后 getRays(),二维数组的第一个元素是

有没有线程发生可能与数组中的物体干扰,所以我困惑至于他们如何能够只测试后的时刻,它们包含有效对象。

什么是错的这个code&放;我该如何解决这个问题?

 进口java.awt中的*。
进口java.awt.event.ActionEvent中;
导入的java.awt.geom *。
进口java.awt.image.BufferedImage中;
导入java.util.logging的*。
进口的javax.swing *。
进口javax.swing.border.EmptyBorder中;公共类TestNullOn2DArray {    公共静态无效的主要(字串[] args){
        可运行R =新的Runnable(){            @覆盖
            公共无效的run(){
                桂=新的GUI();                JFrame的F =新的JFrame(测试空二维阵列);
                f.add(gui.getContainer());
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setLocationByPlatform(真);                f.pack();
                f.setMinimumSize(f.getSize());
                f.setVisible(真);
                gui.plot();
            }
        };
        SwingUtilities.invokeLater(R);
    }
}类GUI {    记录器记录= Logger.getAnonymousLogger();
    私人的JPanel容器;
    JLabel的输出;
    私人的JMenuBar菜单栏;
    私人的BufferedImage帆布;
    私人CustomModel模型=
            新CustomModel(5,1,.66f);
    私人INT defaultPositionNumber = 5;
    私人INT defaultAngleNumber = 5;    公共无效情节(){
        射线[] []光线= model.getRays();
        log.log(Level.INFO,霞光:+射线);
        为(中间体二= 0; II蛋白酶rays.length;ⅱ++){
            对于(INT JJ = 0; JJ<光线[II]。长度; JJ ++){
                一缕一缕光线= [II] [林俊杰];
                log.log(Level.INFO,雷:+射线);
                ray.resolve();
            }
        }
    }    公众的JPanel getContainer(){
        如果(集装箱== NULL){
            集装箱=新JPanel(新的BorderLayout(5,5));
            container.setBorder(新EmptyBorder(4,4,4,4));            ImageIcon的图标=新的ImageIcon(getCanvas());
            输出=新的JLabel(图标);
            container.add(新JScrollPane的(输出),BorderLayout.CENTER);
        }
        返回容器中;
    }    公共无效refreshCanvas(){
        模型=新CustomModel(5,6,.66f);
        帆布= NULL;
        BufferedImage的BI = getCanvas();
        output.setIcon(新的ImageIcon(BI));
    }    公共无效initializeRays(Graphics2D的G){
        log.log(Level.INFOinitializeRays());        INT由startAngle = 1;
        INT numberAngles = defaultAngleNumber;
        INT INC = 90 / numberAngles;
        INT numberPositions = defaultPositionNumber;
        雷[] [] =光线雷新[numberAngles] [numberPositions];
        g.setTransform(AffineTransform.getTranslateInstance(0D,0D));
        为(中间体二= rays.length - 1;ⅱ大于0; ii--){
            对于(INT JJ = 0; JJ<光线[0]。长度; JJ ++){
                GP的GeneralPath =新GeneralPath();                双拉德= 2D * Math.PI *(由startAngle +(INC * II))/ 360D;
                双X = 400D;
                双Y = 100D;
                双yStart = Y - (Math.sin(拉德)* 100D);
                双XSTART = X +(Mat​​h.cos(拉德)* 100D);
                浮R = 2F *(浮点)((拉德/ Math.PI));
                浮动B =(浮点)JJ /(浮点)射线[0]。长度;
                色色=新的色彩(R,1 - R,B,.6f);
                g.setColor(颜色);
                g.drawLine((INT)X,(INT)Y(INT)XSTART,(INT)yStart);
                gp.moveTo(XSTART,yStart);
                gp.lineTo(X,Y);
                gp.closePath();
                一缕一缕=新雷(GP,颜色);
                log.log(Level.INFO,+射线);
                光线[II] [林俊杰] =射线;
            }
        }
        model.setRays(线);
        如果(输出!= NULL){
            output.repaint();
        }
    }    公众的BufferedImage getCanvas(){
        如果(帆布== NULL){
            尺寸大小= model.get preferredSize();
            INT W = size.width;
            INT H = size.height;
            帆布=新的BufferedImage(W,H,BufferedImage.TYPE_INT_ARGB);
            Graphics2D的G = canvas.createGraphics();            g.setColor(Color.WHITE);
            g.fillRect(0,0,W,H);
            g.setColor(新颜色(125,27,155,127));            initializeRays(G);            g.dispose();
        }
        返回帆布;
    }
}类CustomModel {    私人诠释宽度;
    私人诠释层;
    私人浮动抵消;
    私人雷[] []照射;
    私人记录器记录= Logger.getAnonymousLogger();    公共CustomModel(INT宽度,诠释层,浮偏移){
        this.width =宽度;
        this.layers =层;
        this.offset =偏移;
    }    公共Line2D.Double getLineOfLasSegment(){
        Line2D.Double行=新Line2D.Double(0D,0D,1D,1D);
        回线;
    }    公共尺寸的get preferredSize(){
        INT W = 600;
        INT H = 300;
        尺寸prefSize =新尺寸(W,H);
        返回prefSize;
    }    公众诠释的getWidth(){
        返回宽度;
    }    公共无效setWidth(int width)将{
        this.width =宽度;
    }    公众诠释getLayers(){
        返回层;
    }    公共无效setLayers(INT层){
        this.layers =层;
    }    公共雷[] [] getRays(){
        为(中间体二= 0; II蛋白酶rays.length;ⅱ++){
            对于(INT JJ = 0; JJ<光线[II]。长度; JJ ++){
                log.log(Level.INFO,雷:+ this.rays [II] [林俊杰]);
            }
        }
        返回光线;
    }    公共无效setRays(雷[] []射线){
        this.rays =光线;
        为(中间体二= 0; II蛋白酶rays.length;ⅱ++){
            对于(INT JJ = 0; JJ<光线[II]。长度; JJ ++){
                //一缕一缕光线= [II] [林俊杰];
                this.rays [II] [JJ] =射线[II] [JJ];
                log.log(Level.INFO,雷:+ this.rays [II] [林俊杰]);
            }
        }
    }    公众持股量的getOffset(){
        返回偏移;
    }    公共无效setOffset(浮点偏移){
        this.offset =偏移;
    }
}雷类{    私人最终记录器记录= Logger.getAnonymousLogger();
    私人的GeneralPath路径;
    私人布尔开始= FALSE;
    私人色彩的颜色;    雷(的GeneralPath路径,色色){
        this.path =路径;
        this.color =颜色;
    }    公共无效解析(){
        logger.log(Level.INFO..resolving。);
    }    公众的GeneralPath的getPath(){
        返回路径;
    }    公共布尔isStarted(){
        返回开始;
    }    @覆盖
    公共字符串的toString(){
        字符串s =雷
                +开始=+启动;
        返回S;
    }
}

输出

这显示输出的最后部分检查什么 getRays()将返回,随后NPE。

  // ...
2013年6月29日下午4时56分55秒CustomModel getRays
INFO:雷:雷:开始= FALSE
2013年6月29日下午4时56分55秒的GUI情节
INFO:光芒:[LRay; @ 1a9876e
2013年6月29日下午4时56分55秒的GUI情节
INFO:雷:空
在异常线程AWT-EventQueue的-0显示java.lang.NullPointerException
        在GUI.plot(TestNullOn2DArray.java:52)
        在TestNullOn2DArray $ 1.run(TestNullOn2DArray.java:26)
        在java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
        在java.awt.EventQueue.dispatchEventImpl(EventQueue.java:727)
        在java.awt.EventQueue.access $ 200(EventQueue.java:103)
        在java.awt.EventQueue中的$ 3.run(EventQueue.java:688)
        在java.awt.EventQueue中的$ 3.run(EventQueue.java:686)
        在java.security.AccessController.doPrivileged(本机方法)
        在java.security.ProtectionDomain $ 1.doIntersectionPrivilege(​​ProtectionDomain.java:76)
        在java.awt.EventQueue.dispatchEvent(EventQueue.java:697)
        在java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
        在java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
        在java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
        在java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
...


解决方案

通过我的调试器看着它,它看起来好像一切在射线[0] 为空。一切的其他的是present。

这样,通过跟踪挖掘,相信已经发现的数据摆在首位,,并把那里的原因的原因第一行是空的:


  1. 我们称之为 f.add(gui.getContainer()); 。这似乎无伤大雅在其本身,而是让我们看看 getContainer 正在做...


  2. 我们实例化 ImageIcon的图标=新的ImageIcon(getCanvas()); 。再次,无伤大雅,但让我们再次下井兔子洞...


  3. 我们再调用(最终) initializeRays(G); getCanvas()!发生了什么事错在这里? 此: 的for(int II = rays.length - 1;二大于0;二 - )


好吧,你计算的向后的。怪异,并且只能在极少数情况下做到的,但我想你有你的理由。但是,有两个卡口向后计数:


  • 您需要长度为n-1,你做启动;和

  • 您的循环条件必须比的或等于的0,你的的有状态。
  • 更大

将其更改为包括大于或等于-进行测试,你不会有任何更多的NPE。

I have written this code (self contained) which throws an NPE that has me confounded. It involves a 2D array of Ray objects used in a model. The Ray objects are initialized and set to the model. When they are required outside the model, the code calls model.getRays(). At that point the code iterates the 2D array & logs each object, because.. A mere 2-3 lines after the code calls getRays(), the first element of the 2D array is null!

There are no threads happening that might interfere with the objects in the array, so I am confounded as to how they could be null only moments after testing that they contain valid objects.

What is wrong with this code & how do I fix it?

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.util.logging.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class TestNullOn2DArray {

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                GUI gui = new GUI();

                JFrame f = new JFrame("Test Null On 2D Array");
                f.add(gui.getContainer());
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setLocationByPlatform(true);

                f.pack();
                f.setMinimumSize(f.getSize());
                f.setVisible(true);
                gui.plot();
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

class GUI {

    Logger log = Logger.getAnonymousLogger();
    private JPanel container;
    JLabel output;
    private JMenuBar menuBar;
    private BufferedImage canvas;
    private CustomModel model =
            new CustomModel(5, 1, .66f);
    private int defaultPositionNumber = 5;
    private int defaultAngleNumber = 5;

    public void plot() {
        Ray[][] rays = model.getRays();
        log.log(Level.INFO, "Rays: " + rays);
        for (int ii = 0; ii < rays.length; ii++) {
            for (int jj = 0; jj < rays[ii].length; jj++) {
                Ray ray = rays[ii][jj];
                log.log(Level.INFO, "Ray: " + ray);
                ray.resolve();
            }
        }
    }

    public JPanel getContainer() {
        if (container == null) {
            container = new JPanel(new BorderLayout(5, 5));
            container.setBorder(new EmptyBorder(4, 4, 4, 4));

            ImageIcon icon = new ImageIcon(getCanvas());
            output = new JLabel(icon);
            container.add(new JScrollPane(output), BorderLayout.CENTER);
        }
        return container;
    }

    public void refreshCanvas() {
        model = new CustomModel(5, 6, .66f);
        canvas = null;
        BufferedImage bi = getCanvas();
        output.setIcon(new ImageIcon(bi));
    }

    public void initializeRays(Graphics2D g) {
        log.log(Level.INFO, "initializeRays()");

        int startAngle = 1;
        int numberAngles = defaultAngleNumber;
        int inc = 90 / numberAngles;
        int numberPositions = defaultPositionNumber;
        Ray[][] rays = new Ray[numberAngles][numberPositions];
        g.setTransform(AffineTransform.getTranslateInstance(0d, 0d));
        for (int ii = rays.length - 1; ii > 0; ii--) {
            for (int jj = 0; jj < rays[0].length; jj++) {
                GeneralPath gp = new GeneralPath();

                double rads = 2d * Math.PI * (startAngle + (inc * ii)) / 360d;
                double x = 400d;
                double y = 100d;
                double yStart = y - (Math.sin(rads) * 100d);
                double xStart = x + (Math.cos(rads) * 100d);
                float r = 2f * (float) ((rads / Math.PI));
                float b = (float) jj / (float) rays[0].length;
                Color color = new Color(r, 1 - r, b, .6f);
                g.setColor(color);
                g.drawLine((int) x, (int) y, (int) xStart, (int) yStart);
                gp.moveTo(xStart, yStart);
                gp.lineTo(x, y);
                gp.closePath();
                Ray ray = new Ray(gp, color);
                log.log(Level.INFO, "" + ray);
                rays[ii][jj] = ray;
            }
        }
        model.setRays(rays);
        if (output != null) {
            output.repaint();
        }
    }

    public BufferedImage getCanvas() {
        if (canvas == null) {
            Dimension size = model.getPreferredSize();
            int w = size.width;
            int h = size.height;
            canvas = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = canvas.createGraphics();

            g.setColor(Color.WHITE);
            g.fillRect(0, 0, w, h);
            g.setColor(new Color(125, 27, 155, 127));

            initializeRays(g);

            g.dispose();
        }
        return canvas;
    }
}

class CustomModel {

    private int width;
    private int layers;
    private float offset;
    private Ray[][] rays;
    private Logger log = Logger.getAnonymousLogger();

    public CustomModel(int width, int layers, float offset) {
        this.width = width;
        this.layers = layers;
        this.offset = offset;
    }

    public Line2D.Double getLineOfLasSegment() {
        Line2D.Double line = new Line2D.Double(0d, 0d, 1d, 1d);
        return line;
    }

    public Dimension getPreferredSize() {
        int w = 600;
        int h = 300;
        Dimension prefSize = new Dimension(w, h);
        return prefSize;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getLayers() {
        return layers;
    }

    public void setLayers(int layers) {
        this.layers = layers;
    }

    public Ray[][] getRays() {
        for (int ii = 0; ii < rays.length; ii++) {
            for (int jj = 0; jj < rays[ii].length; jj++) {
                log.log(Level.INFO, "Ray: " + this.rays[ii][jj]);
            }
        }
        return rays;
    }

    public void setRays(Ray[][] rays) {
        this.rays = rays;
        for (int ii = 0; ii < rays.length; ii++) {
            for (int jj = 0; jj < rays[ii].length; jj++) {
                //Ray ray = rays[ii][jj];
                this.rays[ii][jj] = rays[ii][jj];
                log.log(Level.INFO, "Ray: " + this.rays[ii][jj]);
            }
        }
    }

    public float getOffset() {
        return offset;
    }

    public void setOffset(float offset) {
        this.offset = offset;
    }
}

class Ray {

    private final Logger logger = Logger.getAnonymousLogger();
    private GeneralPath path;
    private boolean started = false;
    private Color color;

    Ray(GeneralPath path, Color color) {
        this.path = path;
        this.color = color;
    }

    public void resolve() {
        logger.log(Level.INFO, "..resolving.");
    }

    public GeneralPath getPath() {
        return path;
    }

    public boolean isStarted() {
        return started;
    }

    @Override
    public String toString() {
        String s = "Ray: "
                + "  started=" + started;
        return s;
    }
}

Output

This shows the last part of the output checking what getRays() will return, followed by the NPE.

// ...
Jun 29, 2013 4:56:55 PM CustomModel getRays
INFO: Ray: Ray:   started=false
Jun 29, 2013 4:56:55 PM GUI plot
INFO: Rays: [[LRay;@1a9876e
Jun 29, 2013 4:56:55 PM GUI plot
INFO: Ray: null
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at GUI.plot(TestNullOn2DArray.java:52)
        at TestNullOn2DArray$1.run(TestNullOn2DArray.java:26)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
        at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:727)
        at java.awt.EventQueue.access$200(EventQueue.java:103)
        at java.awt.EventQueue$3.run(EventQueue.java:688)
        at java.awt.EventQueue$3.run(EventQueue.java:686)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:697)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
...

解决方案

Looking at it through my debugger, it looks like everything at ray[0] is null. Everything else is present.

So, digging through the trace, I believe to have found the reason that data is put there in the first place, and why the first row is empty:

  1. We call f.add(gui.getContainer());. This seem innocuous in and of itself, but let's see what getContainer is doing...

  2. We instantiate ImageIcon icon = new ImageIcon(getCanvas());. Again, innocuous, but let's go down the rabbit hole again...

  3. We then call (finally) initializeRays(g); in getCanvas()! What's going wrong here? This: for (int ii = rays.length - 1; ii > 0; ii--)

Okay, you're counting backwards. Weird, and only should be done in rare cases, but I suppose you have your reasons. But, there's two catches to counting backwards:

  • You need to start at length n-1, which you do; and
  • Your loop condition must be greater than or equal to 0. You do not have that condition.

Change it to include the greater-than or equal-to test, and you will not have any more NPEs.

这篇关于NullPointerException异常的二维数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆