调试技巧(学习笔记)

  1. 用下面的方法打印或记录任意变量的值 System.out.println("x="+x);
    Logger.getGlobal().info("x="+x);
    如果x是一个数值,则会被转换成等价的字符串。如果x是一个对象,那么Java会调用这个对象的toString方法。要想获得隐式参数对象的状态,可以打印this对象的状态
    Logger.getGlobal().info("this=+this);
    Java类库中的绝大多数类都覆盖toString方法,以便能提供有用的类信息。这样会使调试更加便捷。在你自定义的类中也应该这么做。
  2. 可以在每一个类中放一个单独的main方法。这样就能提供一个单元测试桩,能独立地测试类。

上述方法代码说明

package com.zhd.DebugTest;

import java.util.logging.Logger;

public class DebugTest {
    private String name="baby";
    public static void main(String[] args){
        int age=22;
        var player=new DebugTest();
        System.out.println("age="+age);//输出值
        System.out.println("this"+player);//输出对象状态
        Logger.getGlobal().info("age="+age);//日志记录值
        player.setName("33");
    }

    public void setName(String name) {
        this.name = name;
        Logger.getGlobal().info("this:"+this);//获得隐式参数对象的状态
    }

    @Override
    public String toString() {
        return "DebugTest{" +
                "name='" + name + '\'' +
                '}';
    }
}

在这里插入图片描述

  1. JUnit是个非常流行的单元测试框架,利用他们可以很容易组织测试用例套件,https://junit.org/junit5/docs/current/user-guide/
  2. 日志代理(logging
    proxy)是一个子类的对象,它可以截获方法调用,记录日志,然后调用超类中的方法。例如,如果在调用Random类的nextDouble方法时出现了问题,就可以如下创建一个代理对象,这是一个匿名子类的实例:
var generator=new Random(){
public double nextDouble(){
double result=super.nextDouble();
Logger.getGlobal().info("nextDouble:"+result);
return result;
}
}

只要调用nextDouble 方法,就会生成一个日志消息。要想知道谁调用这个方法,可以生成一个堆栈轨迹

代码说明

package com.zhd.DebugTest;

import java.util.Random;
import java.util.logging.Logger;

public class DebugTest {
    private String name="baby";
    private double getNumber;
    public static void main(String[] args){
        int age=22;
        var player=new DebugTest();
        System.out.println("age="+age);//输出值
        System.out.println("this"+player);//输出对象状态
        Logger.getGlobal().info("age="+age);//日志记录值
        player.setName("33");
        var generator=new Random(){//创建匿名子类
            public double nextDouble(){
                double result=super.nextDouble();
                Logger.getGlobal().info("nextDouble:"+result);//截获方法调用 记录日志
                Thread.dumpStack();//获得堆栈轨迹
                return result;
            }
        };
        player.setGetNumber(generator.nextDouble());
    }

    public void setGetNumber(double getNumber) {
        this.getNumber = getNumber;
    }

    public void setName(String name) {
        this.name = name;
        Logger.getGlobal().info("this:"+this);//获得隐式参数对象的状态
    }

    @Override
    public String toString() {
        return "DebugTest{" +
                "name='" + name + '\'' +
                '}';
    }
}

 Thread.dumpStack();//获得堆栈轨迹

运行截图

在这里插入图片描述

  1. 利用Throwable类的printStackTrace方法可以从任意的异常对象获得堆栈轨迹。下面的代码将捕获任意异常,打印这个异常对象和堆栈轨迹,然后重新抛出异常,以便找到相应的处理器。

- 代码说明

  //方法一
        try{
            //给出一个有隐患的例子 除数为零
            Scanner input = new Scanner(System.in);
            System.out.println("Enter two integers: ");
            int num1 = input.nextInt();
            int num2 = input.nextInt();
            System.out.println(num1 / num2);
        }catch(Throwable t){
            t.printStackTrace();
            throw t;
        }
        //方法二
//        Scanner input = new Scanner(System.in);
//        System.out.println("Enter two integers: ");
//        int num1 = input.nextInt();
//        int num2 = input.nextInt();
//        System.out.println(num1 / num2);

方法二 不用printStackTrace
在这里插入图片描述
方法一
在这里插入图片描述
可以看到确实将捕获任意异常,打印这个异常对象和堆栈轨迹,然后重新抛出异常
当然也不一定非要通过捕获异常来生成堆栈轨迹,在代码的某个位置插入这个Thread.dumpStack();也可以获得堆栈轨迹

  1. 一般来说,堆栈轨迹显示在System.err上。如果想要记录或显示堆栈轨迹,可以如下将它捕获到一个字符串中:
  var out=new StringWriter();
        new Throwable().printStackTrace(new PrintWriter(out));
        String description=out.toString();
        System.out.println(description);

输出如下
在这里插入图片描述

  1. . 通常将程序错误记录到一个文件中会很有用。不过错误会发送到System.err,而不是System.out
    所以不能通过运行java Myprogram>errors.txt而应当用java MyProgram 2>error.txt

在这里插入图片描述
是会在你的包内生成一个errors.txt文件的
要想在同一个文件中同时捕获System.err 和System.out,需要使用以下命令java DebugTest 1> errors.txt 2>&1

  1. 在System.err中显示未捕获的异常的堆栈轨迹不是理想方法,更好的是把这些方法记录到一个文件中。可以用静态方法Thread.setDefaultUncaughtExceptionHandler改变未捕获异常的处理器
  Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){
            public void uncaughtException(Thread t,Throwable e){
                //save information in log file 
//                Logger.getGlobal().info(t + " throws exception: " + e);
            }
        });

说是save information in log file ,我就直接把他放全局日志管理器了,不知道具体怎么操作,里面的信息t + " throws exception: " + e应该就是这个,把这个放到具体文件应该就好

  • 要想观察类的加载过程,启用java虚拟机是可以使用-verbose标志。这样就可以看到
    在这里插入图片描述
    老大一堆这玩意儿 这对玩意儿对

诊断类路径问题会很有帮助

划重点

  1. -Xlint选项告诉编译器找出常见的代码问题。例如,如果使用下面这条命令编译
  javac -Xlint sourceFiles

当switch语句中缺少break语句时,编译器就会报告这个问题
下面简单的加了点代码

 switch (age){
            case 22://这里没加breakSystem.out.println("I am " + age);
        }

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值