当前位置: 代码网 > it编程>编程语言>Java > Java入门指南之IDEA高效调试与数组

Java入门指南之IDEA高效调试与数组

2026年05月14日 Java 我要评论
前言作为 java 开发者,调试能力决定排错效率,数组功底决定代码质量。这篇文章把 idea 调试全套技巧、数组从基础到进阶的知识点一次性讲透,适合新手夯实基础、老手快速回顾。一、先搞懂:什么是程序调

前言

作为 java 开发者,调试能力决定排错效率,数组功底决定代码质量。这篇文章把 idea 调试全套技巧、数组从基础到进阶的知识点一次性讲透,适合新手夯实基础、老手快速回顾。

一、先搞懂:什么是程序调试?

调试(debugging)不是简单 “改代码”,而是定位问题 → 缩小范围 → 修复验证的完整过程。

  • 小代码:肉眼读 + 打印日志
  • 复杂项目:必须用 ide 调试器

idea 内置的调试器是 java 开发效率神器,掌握它能让你快速揪出隐藏 bug。

二、idea 调试

1. 调试三步基础

  1. 打断点:代码行号左侧单击,出现红色圆点
  2. 启动调试:右键 → debug
  3. 控制执行:用快捷键一步步观察变量与流程

2. 核心调试操作

操作快捷键作用
逐过程(不进方法)f8一行一行走,跳过方法内部
逐语句(进入方法)f7进入自定义方法内部
强制进入alt+shift+f7强行进入 jdk 库方法 / 无源码方法
跳出方法shift+f8执行完当前方法并返回调用处
运行到光标alt+f9直接跳到光标所在行
恢复程序f9跳到下一个断点 / 结束
重新调试ctrl+f5重启调试会话
停止调试ctrl+f2终止调试
查看所有断点ctrl+shift+f8统一管理断点

3. 进阶:条件断点

循环几百次只想在特定值停下?用条件断点

  1. 右键断点
  2. 填入条件(如 i == 20
  3. 调试只会在条件成立时暂停

4. 调试面板看什么?

  • debugger 面板:调用栈 + 实时变量值 + 表达式计算
  • console 面板:程序正常输出 / 异常信息
  • mute breakpoints:一键临时屏蔽所有断点

三、java 数组

数组是 java 最基础的数据结构,相同类型、连续内存、下标从 0 开始,这三个特征刻在心里。

1. 为什么要用数组?

不用数组:存 100 个成绩要定义 100 个变量。用数组:一行搞定,遍历、修改、传参都更简洁。

2. 数组创建与初始化(两种方式)

动态初始化(指定长度)

int[] arr = new int[5]; // 默认值:0
string[] strs = new string[3]; // 默认值:null

静态初始化(指定内容)

// 完整写法
int[] arr1 = new int[]{1,2,3,4,5};
// 简写(推荐)
int[] arr2 = {1,2,3,4,5};

⚠️ 注意:

  • 简写形式不能拆分两行写
  • 下标范围:[0, length),越界抛 arrayindexoutofboundsexception

3. 数组遍历:3 种写法

  1. 普通 for 循环(可修改元素)
for (int i = 0; i < arr.length; i++) {
    system.out.println(arr[i]);
}
  1. for-each 循环(只读更简洁)
for (int num : arr) {
    system.out.println(num);
}
  1. arrays.tostring(快速打印)
system.out.println(arrays.tostring(arr));

4. 关键:数组是引用类型

  • 基本类型:变量存
  • 引用类型:变量存堆内存地址
  • arr1 = arr2指向同一块内存,不是拷贝
int[] a = {1,2,3};
int[] b = a;
b[0] = 100; // a[0] 也会变成 100
  • null:空引用,访问会抛 nullpointerexception

5. 数组作为方法参数 / 返回值

  • 传基本类型:值传递,不影响原变量
  • 传数组:引用传递,方法内修改会影响原数组
  • 数组可直接作为返回值,返回一组数据

6. 数组常用工具方法(java.util.arrays)

arrays.tostring(arr):数组转字符串

import java.util.arrays;

/**
 * arrays.tostring():数组转字符串
 * 特点:
 * 1. 一维数组直接输出易读格式
 * 2. 多维数组需用 arrays.deeptostring()
 * 3. 空数组输出 []
 */
public class arraystostringdemo {
    public static void main(string[] args) {
        // 测试1:普通int数组
        int[] intarr = {1, 2, 3, 4, 5};
        system.out.println("int数组转字符串:" + arrays.tostring(intarr));

        // 测试2:字符串数组
        string[] strarr = {"java", "数组", "工具类"};
        system.out.println("字符串数组转字符串:" + arrays.tostring(strarr));

        // 测试3:空数组
        int[] emptyarr = new int[0];
        system.out.println("空数组转字符串:" + arrays.tostring(emptyarr));

        // 测试4:多维数组(注意:一维tostring不适用,需用deeptostring)
        int[][] multiarr = {{1,2}, {3,4}};
        system.out.println("多维数组用tostring:" + arrays.tostring(multiarr)); // 输出地址
        system.out.println("多维数组用deeptostring:" + arrays.deeptostring(multiarr)); // 正确输出
    }
}


/*结果:
int数组转字符串:[1, 2, 3, 4, 5]
字符串数组转字符串:[java, 数组, 工具类]
空数组转字符串:[]
多维数组用tostring:[[i@7852e922, [i@4e25154f]
多维数组用deeptostring:[[1, 2], [3, 4]]
*/

arrays.copyof(arr, len):数组拷贝(新对象)

import java.util.arrays;

/**
 * arrays.copyof():数组拷贝
 * 特点:
 * 1. 返回新数组,原数组不受影响(深拷贝)
 * 2. len < 原长度:截取前len个元素
 * 3. len > 原长度:补默认值(int补0,string补null)
 */
public class arrayscopyofdemo {
    public static void main(string[] args) {
        int[] originalarr = {10, 20, 30, 40, 50};
        system.out.println("原数组:" + arrays.tostring(originalarr));

        // 场景1:拷贝长度 = 原长度(完整拷贝)
        int[] copyfull = arrays.copyof(originalarr, originalarr.length);
        system.out.println("完整拷贝:" + arrays.tostring(copyfull));

        // 场景2:拷贝长度 < 原长度(截取)
        int[] copyshort = arrays.copyof(originalarr, 3);
        system.out.println("截取前3个元素:" + arrays.tostring(copyshort));

        // 场景3:拷贝长度 > 原长度(补默认值)
        int[] copylong = arrays.copyof(originalarr, 7);
        system.out.println("补0到7个元素:" + arrays.tostring(copylong));

        // 验证:修改新数组,原数组不变
        copyfull[0] = 999;
        system.out.println("修改后新数组:" + arrays.tostring(copyfull));
        system.out.println("原数组仍不变:" + arrays.tostring(originalarr));
    }
}

/*结果:
原数组:[10, 20, 30, 40, 50]
完整拷贝:[10, 20, 30, 40, 50]
截取前3个元素:[10, 20, 30]
补0到7个元素:[10, 20, 30, 40, 50, 0, 0]
修改后新数组:[999, 20, 30, 40, 50]
原数组仍不变:[10, 20, 30, 40, 50]
*/

arrays.copyofrange(arr, from, to):范围拷贝

import java.util.arrays;

/**
 * arrays.copyofrange():范围拷贝
 * 特点:
 * 1. 左闭右开:[from, to)
 * 2. from = 0 且 to = 原长度 → 等价于 copyof
 * 3. 下标越界会抛 arrayindexoutofboundsexception
 */
public class arrayscopyofrangedemo {
    public static void main(string[] args) {
        string[] originalarr = {"a", "b", "c", "d", "e", "f"};
        system.out.println("原数组:" + arrays.tostring(originalarr));

        // 场景1:拷贝中间范围(下标1到4,包含1,不包含4)
        string[] range1 = arrays.copyofrange(originalarr, 1, 4);
        system.out.println("拷贝[1,4):" + arrays.tostring(range1)); // [b, c, d]

        // 场景2:拷贝从0到末尾(完整拷贝)
        string[] range2 = arrays.copyofrange(originalarr, 0, originalarr.length);
        system.out.println("拷贝完整数组:" + arrays.tostring(range2));

        // 场景3:拷贝到超出原长度(补默认值null)
        string[] range3 = arrays.copyofrange(originalarr, 3, 8);
        system.out.println("拷贝[3,8)(补null):" + arrays.tostring(range3));
    }
}

/*结果:
原数组:[a, b, c, d, e, f]
拷贝[1,4):[b, c, d]
拷贝完整数组:[a, b, c, d, e, f]
拷贝[3,8)(补null):[d, e, f, null, null]
*/

arrays.sort(arr):高效排序

import java.util.arrays;

/**
 * arrays.sort():数组排序
 * 特点:
 * 1. 基本类型数组:快速排序/双轴快排,效率高
 * 2. 直接修改原数组(原地排序)
 * 3. 字符串数组:按unicode编码升序(字母a-z对应升序)
 */
public class arrayssortdemo {
    public static void main(string[] args) {
        // 场景1:int数组升序排序
        int[] intarr = {5, 2, 9, 1, 5, 6};
        system.out.println("排序前int数组:" + arrays.tostring(intarr));
        arrays.sort(intarr);
        system.out.println("排序后int数组:" + arrays.tostring(intarr));

        // 场景2:字符串数组排序
        string[] strarr = {"java", "python", "c", "javascript"};
        system.out.println("\n排序前字符串数组:" + arrays.tostring(strarr));
        arrays.sort(strarr);
        system.out.println("排序后字符串数组:" + arrays.tostring(strarr));

        // 场景3:指定范围排序(sort(arr, from, to):左闭右开)
        int[] rangearr = {10, 5, 8, 2, 7, 1};
        system.out.println("\n排序前范围数组:" + arrays.tostring(rangearr));
        arrays.sort(rangearr, 1, 5); // 只排序下标1到4的元素
        system.out.println("排序[1,5)后:" + arrays.tostring(rangearr));
    }
}

/*结果:
排序前int数组:[5, 2, 9, 1, 5, 6]
排序后int数组:[1, 2, 5, 5, 6, 9]

排序前字符串数组:[java, python, c, javascript]
排序后字符串数组:[c, java, javascript, python]

排序前范围数组:[10, 5, 8, 2, 7, 1]
排序[1,5)后:[10, 2, 5, 7, 8, 1]
*/

arrays.binarysearch(arr, key):有序数组二分查找

import java.util.arrays;

/**
 * arrays.binarysearch():二分查找
 * 前提:数组必须是升序排序后的!
 * 特点:
 * 1. 找到:返回元素下标
 * 2. 未找到:返回 -(插入点) - 1
 * 3. 有重复元素:返回任意一个匹配下标(不保证是第一个)
 */
public class arraysbinarysearchdemo {
    public static void main(string[] args) {
        int[] sortedarr = {1, 2, 3, 5, 7, 9, 10}; // 必须先排序!
        system.out.println("有序数组:" + arrays.tostring(sortedarr));

        // 场景1:查找存在的元素
        int key1 = 7;
        int index1 = arrays.binarysearch(sortedarr, key1);
        system.out.println("查找" + key1 + ":下标=" + index1);

        // 场景2:查找不存在的元素
        int key2 = 4;
        int index2 = arrays.binarysearch(sortedarr, key2);
        system.out.println("查找" + key2 + ":返回值=" + index2 + "(插入点是3,-(3)-1=-4)");

        // 场景3:查找超出范围的元素
        int key3 = 11;
        int index3 = arrays.binarysearch(sortedarr, key3);
        system.out.println("查找" + key3 + ":返回值=" + index3 + "(插入点是7,-(7)-1=-8)");

        // 错误示例:未排序数组查找(结果不可靠)
        int[] unsortedarr = {5, 2, 9};
        int index4 = arrays.binarysearch(unsortedarr, 2);
        system.out.println("\n未排序数组查找2:" + index4 + "(结果错误,不可信)");
    }
}

/*结果:
有序数组:[1, 2, 3, 5, 7, 9, 10]
查找7:下标=4
查找4:返回值=-4(插入点是3,-(3)-1=-4)
查找11:返回值=-8(插入点是7,-(7)-1=-8)

未排序数组查找2:-1(结果错误,不可信)
*/

7. 经典算法手写(面试常考)

顺序查找

/**
 * 顺序查找(线性查找)
 * 核心:逐个遍历、逐一比较,找到返回下标,未找到返回-1
 * 适用:无序/有序数组都能查,优点是简单,缺点是效率低(时间复杂度 o(n))
 */
public class sequentialsearch {
    public static void main(string[] args) {
        // 测试数组(无序也能查)
        int[] arr = {8, 3, 9, 7, 2, 5, 1, 6, 4};
        int target = 7;
        
        // 调用查找方法
        int index = sequentialsearch(arr, target);
        
        // 输出结果
        if (index != -1) {
            system.out.println("找到目标值 " + target + ",下标为:" + index);
        } else {
            system.out.println("未找到目标值 " + target);
        }
    }

    /**
     * 顺序查找核心方法
     * @param arr 待查找的数组
     * @param target 要找的目标值
     * @return 找到返回下标,未找到返回-1
     */
    public static int sequentialsearch(int[] arr, int target) {
        // 健壮性处理:数组为空/长度为0,直接返回-1
        if (arr == null || arr.length == 0) {
            return -1;
        }
        
        // 遍历数组,逐个比较
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == target) {
                return i; // 找到立即返回下标,无需继续遍历
            }
        }
        
        // 遍历完都没找到,返回-1
        return -1;
    }
}

二分查找(有序数组)

/**
 * 二分查找(折半查找)
 * 核心:利用有序数组特性,每次排除一半元素,效率高(时间复杂度 o(log₂n))
 * 前提:数组必须是有序的(升序/降序,代码需对应调整)
 */
public class binarysearch {
    public static void main(string[] args) {
        // 测试数组(必须是有序数组,这里用升序)
        int[] sortedarr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        int target = 5;
        
        // 调用二分查找方法
        int index = binarysearch(sortedarr, target);
        
        // 输出结果
        if (index != -1) {
            system.out.println("找到目标值 " + target + ",下标为:" + index);
        } else {
            system.out.println("未找到目标值 " + target);
        }
    }

    /**
     * 二分查找核心方法(升序数组)
     * @param sortedarr 有序数组(升序)
     * @param target 要找的目标值
     * @return 找到返回下标,未找到返回-1
     */
    public static int binarysearch(int[] sortedarr, int target) {
        // 健壮性处理
        if (sortedarr == null || sortedarr.length == 0) {
            return -1;
        }
        
        // 定义左右指针
        int left = 0;
        int right = sortedarr.length - 1;
        
        // 循环条件:左指针 <= 右指针(注意是 <=,否则会漏查最后一个元素)
        while (left <= right) {
            // 计算中间下标(避免溢出:等价于 (left + right) / 2,但更安全)
            int mid = left + (right - left) / 2;
            
            if (sortedarr[mid] == target) {
                return mid; // 找到目标,返回下标
            } else if (sortedarr[mid] < target) {
                // 目标在右半部分,左指针右移
                left = mid + 1;
            } else {
                // 目标在左半部分,右指针左移
                right = mid - 1;
            }
        }
        
        // 循环结束仍未找到,返回-1
        return -1;
    }
}

冒泡排序

/**
 * 冒泡排序
 * 核心:相邻元素两两比较,大的元素逐步“冒泡”到数组末尾
 * 优化:如果某一轮没有交换,说明数组已有序,直接退出(减少循环次数)
 * 时间复杂度:最坏 o(n²),最好 o(n)(已排序数组)
 */
public class bubblesort {
    public static void main(string[] args) {
        // 测试数组
        int[] arr = {8, 3, 9, 7, 2, 5, 1, 6, 4};
        system.out.println("排序前:" + arrays.tostring(arr));
        
        // 调用冒泡排序方法
        bubblesort(arr);
        
        // 输出结果
        system.out.println("排序后:" + arrays.tostring(arr));
    }

    /**
     * 冒泡排序核心方法(升序)
     * @param arr 待排序的数组(直接修改原数组)
     */
    public static void bubblesort(int[] arr) {
        // 健壮性处理
        if (arr == null || arr.length <= 1) {
            return; // 空数组/只有1个元素,无需排序
        }
        
        int length = arr.length;
        
        // 外层循环:控制排序轮数(最多 length-1 轮)
        for (int i = 0; i < length - 1; i++) {
            // 标记:本轮是否发生交换
            boolean swapped = false;
            
            // 内层循环:每轮比较到 length-1-i 位置(后i个元素已排好序)
            for (int j = 0; j < length - 1 - i; j++) {
                // 相邻元素比较,前 > 后则交换(升序)
                if (arr[j] > arr[j + 1]) {
                    // 交换两个元素
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    
                    // 标记发生了交换
                    swapped = true;
                }
            }
            
            // 优化:本轮无交换,说明数组已有序,直接退出循环
            if (!swapped) {
                break;
            }
        }
    }
}

数组逆序

/**
 * 数组逆序
 * 核心:双指针法,首尾元素交换,直到指针相遇
 * 优点:时间复杂度 o(n),空间复杂度 o(1)(原地逆序,不额外占用空间)
 */
public class reversearray {
    public static void main(string[] args) {
        // 测试数组
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        system.out.println("逆序前:" + arrays.tostring(arr));
        
        // 调用逆序方法
        reversearray(arr);
        
        // 输出结果
        system.out.println("逆序后:" + arrays.tostring(arr));
    }

    /**
     * 数组逆序核心方法(原地逆序,直接修改原数组)
     * @param arr 待逆序的数组
     */
    public static void reversearray(int[] arr) {
        // 健壮性处理
        if (arr == null || arr.length <= 1) {
            return; // 空数组/只有1个元素,无需逆序
        }
        
        // 定义首尾指针
        int left = 0;
        int right = arr.length - 1;
        
        // 循环交换:左指针 < 右指针时交换
        while (left < right) {
            // 交换首尾元素
            int temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
            
            // 左指针右移,右指针左移
            left++;
            right--;
        }
    }
}

自定义数组拷贝

/**
 * 自定义数组拷贝
 * 核心:创建新数组,遍历原数组,逐个复制元素到新数组
 * 对比 jdk 自带的 arrays.copyof:逻辑一致,帮你理解底层原理
 */
public class customarraycopy {
    public static void main(string[] args) {
        // 测试数组
        int[] originalarr = {8, 3, 9, 7, 2, 5, 1, 6, 4};
        system.out.println("原数组:" + arrays.tostring(originalarr));
        
        // 调用自定义拷贝方法
        int[] copyarr = customcopyof(originalarr, originalarr.length);
        system.out.println("拷贝数组:" + arrays.tostring(copyarr));
        
        // 验证:修改拷贝数组,原数组不受影响(证明是深拷贝)
        copyarr[0] = 100;
        system.out.println("修改后拷贝数组:" + arrays.tostring(copyarr));
        system.out.println("修改后原数组:" + arrays.tostring(originalarr));
    }

    /**
     * 自定义数组拷贝方法
     * @param original 原数组
     * @param newlength 新数组长度(可大于/小于原数组长度)
     * @return 新的拷贝数组
     */
    public static int[] customcopyof(int[] original, int newlength) {
        // 健壮性处理:原数组为空
        if (original == null) {
            return null;
        }
        
        // 1. 创建新数组(指定长度)
        int[] newarr = new int[newlength];
        
        // 2. 确定要拷贝的元素个数(取原数组长度和新长度的较小值)
        int copylength = math.min(original.length, newlength);
        
        // 3. 遍历原数组,逐个复制到新数组
        for (int i = 0; i < copylength; i++) {
            newarr[i] = original[i];
        }
        
        // 4. 返回新数组(如果新长度 > 原长度,多余位置默认值为0)
        return newarr;
    }
}

8. 二维数组

本质:数组的数组

int[][] arr = {{1,2},{3,4},{5,6}};
// 遍历
for (int i = 0; i < arr.length; i++) {
    for (int j = 0; j < arr[i].length; j++) {
        system.out.print(arr[i][j] + " ");
    }
    system.out.println();
}

四、调试 + 数组:实战组合技巧

  1. 遍历数组时用条件断点,只看目标元素
  2. 调试面板直接查看数组每一位的值
  3. 下标越界时,用调试看循环边界是否正确
  4. 引用传递问题:在面板看地址是否相同

五、总结

  • 调试是程序员的基本功,idea 快捷键用熟效率翻倍
  • 数组是数据结构基石,连续内存、引用类型、下标 0 起步
  • 先会调试排错,再扎实掌握数组,java 基础才算稳

到此这篇关于java入门指南之idea高效调试与数组的文章就介绍到这了,更多相关idea高效调试与java数组内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com