java - 在这种情况下使用空的 catch block 是不好的做法吗?

标签 java nullpointerexception try-catch

我有一个粒子模拟项目,我在过去的几个小时里一直在研究它,我将发布两个类(class)。一种是 Particle 类,一种是 main 和 Canvas 类。我创建一个 Canvas ,然后获取它的 BufferStrategy 和一个要在其上绘制的 Graphics。我使用更新循环来更新每帧的粒子,并使用渲染循环来渲染每帧的粒子。更新和渲染都是通过调用粒子数组列表中每个粒子的自渲染和自更新方法来完成的。现在这是我的问题。我有一个 MouseListener,它可以在中键单击时清除所有粒子,但这会创建一个 NullPointException,因为当更新方法迭代它时,粒子 ArrayList 被清空。

我通过简单地将代码包含在粒子的更新方法中并使用带有空捕获的 try catch 来解决了这个问题,因为当异常发生时无需执行任何操作 - 所有粒子都消失了,因此完成更新并不重要。然而,我读到这是一种不好的形式。有更好的解决方案吗?

我不知道如何使代码段变为粗体。 try catch 位于 Particle 类的末尾附近。

粒子类别:

import java.awt.Graphics;
import java.util.ArrayList;

public class Particle {
    static int G = 1; //gravity constant
    double xPos;
    double yPos;
    double xVel;
    double yVel;
    int radius;
    static int particleCount = 0;
    double mass;


    public Particle(int xp, int yp
            ,double xv,double yv, int r){
        xPos=xp;
        yPos=yp;
        xVel=xv;
        yVel=yv;
        radius=r;
        mass = Math.PI*Math.pow(radius,2);
        particleCount++;
    }

    void drawParticle(Graphics g){
        g.fillOval((int)Math.round(xPos), (int)Math.round(yPos), 2*radius, 2*radius);
    }
    void updateParticle(int thisParticleIndex, ArrayList<Particle> list){
        //update position
        xPos+=xVel;
        yPos+=yVel;

        //update velocity
        //F = G*m1*m2 / r^2
        double M; //let M = m1*m2
        double r;
        double Fx=0;
        double Fy=0;
        double dF;
        double dFx;
        double dFy;
        double theta;

        Particle p;
        try {
            for(int i=0; i<list.size();i++){
                if(i!=thisParticleIndex){
                    p = list.get(i);
                    r = Math.sqrt(Math.pow((p.xPos+p.radius) - (xPos + radius), 2) + 
                            Math.pow((p.yPos+p.radius) - (yPos + radius), 2));
                    if(r<5)
                        continue;
                    M = mass + p.mass;
                    dF = G*M/Math.pow(r,2);
                    theta = Math.atan2((p.yPos+p.radius) - (yPos + radius),
                            (p.xPos+p.radius) - (xPos + radius));
                    dFx = dF*Math.cos(theta);
                    dFy = dF*Math.sin(theta);
                    Fx += dFx;
                    Fy += dFy;
                }
            }
        } catch (NullPointerException e) {
            //This try catch is needed for when all particles are cleared
        }

        xVel += Fx/mass;
        yVel += Fy/mass;
    }
}

Canvas 类:

public class MainAR extends Canvas implements Runnable {
    private static int width = 600;
    private static int height = 600;

    private Thread gameThread;
    private JFrame frame;
    private boolean running = false;

    private ArrayList<Particle> particles = new ArrayList<>();
    private int WIDTH = 800;
    private int HEIGHT = 800;
    private int mouseX = 0;
    private int mouseY = 0;
    private int radius=15;
    private boolean drawMouse = true;
    private boolean mouseDown = false;
    private JLabel instructions;

        public MainAR() {
                setSize(width,height);
                frame = new JFrame();
                frame.setTitle("Particle Simulator");
                frame.add(this);
                frame.pack();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
                start();

                Particle a = new Particle((int)(0.3*WIDTH),(int)(0.3*HEIGHT),0,0,15);
                Particle b = new Particle((int)(0.3*WIDTH),(int)(0.6*HEIGHT),0,0,20);
                Particle c = new Particle((int)(0.6*WIDTH),(int)(0.3*HEIGHT),0,0,10);
                Particle d = new Particle((int)(0.6*WIDTH),(int)(0.6*HEIGHT),0,0,25);

                particles.add(a);
                particles.add(b);
                particles.add(c);
                particles.add(d);

                addMouseMotionListener(new MouseMotionListener(){
                    public void mouseDragged(MouseEvent e) {
                        mouseX = e.getX();
                        mouseY = e.getY();
                        if(SwingUtilities.isLeftMouseButton(e))
                            mouseDown = true;
                    }

                    public void mouseMoved(MouseEvent e) {
                        mouseX = e.getX();
                        mouseY = e.getY();
                    }
                });
                addMouseWheelListener(new MouseWheelListener(){
                    public void mouseWheelMoved(MouseWheelEvent e) {
                        radius -= e.getWheelRotation();
                        if(radius<1)
                            radius = 1;
                    }
                });
                addMouseListener(new MouseListener(){
                    public void mouseClicked(MouseEvent e) {
                        if(SwingUtilities.isLeftMouseButton(e))
                            particles.add(new Particle((int)(mouseX-radius),(int)(mouseY-radius),0,0,radius));
                        if(SwingUtilities.isRightMouseButton(e))
                            instructions.setVisible(false);
                    }
                    public void mouseEntered(MouseEvent e) {
                        drawMouse = true;
                        mouseX = e.getX();
                        mouseY = e.getY();
                    }
                    public void mouseExited(MouseEvent e) {
                        drawMouse = false;
                    }
                    public void mousePressed(MouseEvent e) {
                        if(SwingUtilities.isRightMouseButton(e))
                            instructions.setVisible(false);
                        if(SwingUtilities.isMiddleMouseButton(e)){
                            Particle.particleCount = 0;
                            particles.clear();
                        }

                    }
                    public void mouseReleased(MouseEvent e) {
                        mouseDown = false;
                    }
                });
        }

        public synchronized void start() {
                running = true;
                gameThread = new Thread(this, "Display");
                gameThread.start();
        }

        public synchronized void stop() {
                running = false;
                try {
                        gameThread.join();
                } catch (InterruptedException e) {
                        e.printStackTrace();
                }
        }

        public void run() {
                while(running) {
                    try {
                        Thread.sleep(2);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                        update();
                        render();
                }
        }

        private void update() {
            if(mouseDown)
                particles.add(new Particle((int)(mouseX-radius),(int)(mouseY-radius),0,0,radius));
            for(int i=0; i<particles.size();i++)
                particles.get(i).updateParticle(i,particles);
            frame.setTitle("Particle Simulator" + particles.size() + "particles");
        }

        private void render() {
                BufferStrategy bs = getBufferStrategy();
                if (bs == null){
                        createBufferStrategy(3);
                        return;
                }

                Graphics g = bs.getDrawGraphics();
                ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
                g.setColor(Color.WHITE);
                g.fillRect(0, 0, getWidth(), getHeight());
                g.setColor(Color.BLACK);
                g.fillOval((int)(mouseX-radius), (int)(mouseY-radius), 2*radius, 2*radius);
                for(Particle p : (ArrayList<Particle>)particles.clone()) //cloning prevents Concurrent Modification Exception error
                    p.drawParticle(g);
                g.dispose();
                bs.show();
        }

        public static void main(String[] args){
        MainAR m = new MainAR();

        }
}

PS-我还有另一个快速的次要问题。在我的 Particles 类中使用非私有(private)字段是不好的做法吗?例如我应该代替这个

if(SwingUtilities.isMiddleMouseButton(e)){
                            Particle.particleCount = 0;
                            particles.clear();
                        }

是否使用静态 getter 和 setter 方法来访问 Particle 内的私有(private) static int 粒子计数?

最佳答案

Is using an empty catch block bad practice in this situation?

是的。几乎在所有情况下,使用空的 catch block 都是非常糟糕的做法。这意味着你试图掩盖一些错误的事情。你不是在解决问题,而是在隐藏问题。如果您的程序流程要求有空的 catch block ,那么您在应用它之前必须三思而后行,根据我的说法,您正在处理的流程或要求一定有问题。

an empty catch, because there is nothing necessary to do when the exception occurs

没有。当您遇到任何 Exception 时,您必须采取任何措施,Exception 的含义是您的代码中出现某些错误。

例如,您正在捕获NullPointerException,并且不执行任何操作,您只是继续前进。考虑以下示例,

try {
  checkAeroplane();
} catch(TechnicalProblemException e) {
  //No action needed
}

flyAeroplane();//Crash!!

在多线程环境中,如果多个线程正在操作您的列表,您可能会遇到异常,您应该使用 ArrayList 的线程安全替代方案 CopyOnWriteArrayList除此之外,您应该使用 synchronized停止通过多个线程同时操作您的逻辑。

关于java - 在这种情况下使用空的 catch block 是不好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32411760/

相关文章:

java - 从 Android 中的 Assets 传递路径

java - Java TableRowSorter 中的 NullPointerException

swift - 如何在 Swift 中使用 try-catch?

c# - 从 Azure 表捕获错误的简洁方法(除了字符串匹配?)

java - java 中的正则表达式帮助

java - Hibernate - 替换集合

java - 无法在zk中的列表框模具="select"中设置选定的值

java - Netbeans 中的 NullPointerException

java - 如何处理java.lang.nullpointerException

c# - 为什么我可以在 C# 中编写一个什么都不做的通用 catch 语句?