【面试问题精选】java开发工程师

1.数组的特点?

Java 数组是 定长容器 ,一旦通过语法 数组类型[] 数组名 = new 数组类型[长度]; 初始化后,数组的长度(容量)永久固定,永远不能改变

  • 数组分配的内存空间在初始化时就完全确定,后续无法扩容、无法缩容;
  • 如果想要「扩容」数组,只能新建一个更大的数组,再把原数组的元素复制过去;
  • 可以通过数组的 length 属性 获取数组长度(注意:是属性不是方法,没有小括号 ())。
java 复制代码
public class ArrayDemo {
    public static void main(String[] args) {
        // 初始化一个长度为3的int数组,长度永久固定为3
        int[] arr = new int[3];
        arr[0] = 10;
        arr[1] = 20;
        arr[2] = 30;
        
        System.out.println("数组长度:" + arr.length); // 输出:3
        
        // ❌ 错误写法:length是属性,不能写arr.length(),会编译报错
        // System.out.println(arr.length());
        
        // ❌ 错误:无法修改数组长度,没有setLength方法,编译报错
        // arr.length = 5;
    }
}

Java 数组是同质容器 ,一个数组在定义时就确定了元素类型,数组中只能存放「同一种数据类型」的元素,不允许混合存放不同类型的数据。

  • 支持存储:基本数据类型(int、double、char 等)、引用数据类型(String、对象、数组等);
  • 补充:如果数组的元素类型是 Object(所有类的父类),看似能存不同类型,本质还是存的Object类型,不属于「混合类型」。
java 复制代码
public class ArrayDemo {
    public static void main(String[] args) {
        // ✅ 合法:int数组,只能存int类型
        int[] intArr = {1,2,3,4};
        
        // ✅ 合法:String数组,只能存String类型
        String[] strArr = {"Java","数组","特点"};
        
        // ❌ 非法:int数组中存放字符串,编译直接报错
        // int[] errArr = {1, "abc", 3};
    }
}

Java 数组的元素不能通过元素名访问 ,只能通过 「下标(索引)」 访问,这是数组唯一的访问方式。

核心规则

  1. 数组下标是 从 0 开始的整数
  2. 下标的取值范围:0 <= 下标 < 数组.length
  3. 访问语法:数组名[下标] (取值 / 赋值都用这个语法);
  4. 下标越界后果:运行时抛出 ArrayIndexOutOfBoundsException 异常(编译不报错,运行报错)。
java 复制代码
public class ArrayDemo {
    public static void main(String[] args) {
        int[] arr = {10,20,30};
        // ✅ 合法访问:下标0、1、2
        System.out.println(arr[0]); // 取值:10
        arr[1] = 200; // 赋值:把下标1的元素改为200
        
        // ❌ 非法访问:下标3,超过范围(最大是2),运行时报ArrayIndexOutOfBoundsException
        // System.out.println(arr[3]);
    }
}

因为数组的长度固定、支持下标访问,Java 提供了两种专属的遍历方式,都可以完整遍历数组的所有元素,二者适用场景不同:

1. 普通 for 循环(带下标)

  • 语法:for(int i=0; i<数组.length; i++){ 数组名[i] }
  • 优点:能获取下标,支持「取值 + 赋值」操作,适合需要操作下标的场景(比如元素修改、逆序遍历)。

2. 增强 for 循环(foreach,无下标)

  • 语法:for(元素类型 变量名 : 数组名){ 变量名 }
  • 优点:语法简洁,代码量少;
  • 缺点:无法获取下标只能取值、不能赋值修改数组元素,适合单纯的「读取元素」场景。
java 复制代码
public class ArrayDemo {
    public static void main(String[] args) {
        int[] arr = {10,20,30};
        
        // 方式1:普通for循环(推荐,可取值+赋值)
        for (int i = 0; i < arr.length; i++) {
            arr[i] += 5; // 给每个元素+5,赋值修改
            System.out.println(arr[i]); // 输出:15、25、35
        }
        
        // 方式2:增强for循环(只读,简洁)
        for (int num : arr) {
            System.out.println(num); // 输出:15、25、35
            // num +=5; 无意义,只是修改局部变量,不会改变原数组
        }
    }
}
  • 长度不可变 ,初始化后容量永久固定,通过 length 属性获取长度;
  • 存储同一种数据类型的元素,元素类型统一;
  • 引用类型,栈存地址、堆存实际元素;
  • 通过下标(索引) 访问元素,下标从 0 开始,越界抛运行时异常;
  • 未赋值的元素有默认初始化值,不同类型默认值固定;
  • 支持普通 for 循环、增强 for 循环两种遍历方式;
  • 支持多维数组,本质是「数组的数组」;
  • 元素可以是基本类型,也可以是引用类型。

2.什么是二分查找,基本编程思路是什么?

二分查找的前提条件 :查找的数组 / 集合必须是「有序」的(升序 / 降序均可,常用升序)

时间复杂度为 O(log₂n),n 是数据量,比如找 100 万条数据最多只需要 20 次计算,性能极强。它的查找逻辑特别像「猜数字游戏」:猜一个 1~100 的数字,猜 50,大了就只在 1~49 猜,小了就只在 51~100 猜,每次都把范围缩小一半,直到找到目标值。

举个例子:数组长度n=1024,顺序查找最坏 1024 次,二分查找最坏仅需要 10 次 就一定能找到结果。

有序数组:arr = [1,3,5,7,9,11,13,15] (升序),查找目标值 target = 7

初始化:left=0right=7(数组最后一个元素下标);

第一次循环:mid=(0+7)/2=3arr[3]=7,正好等于目标值 → 返回下标 3,查找结束。

有序数组:arr = [1,3,5,7,9,11,13,15],查找目标值 target = 11

执行步骤:

  • 初始化:left=0right=7
  • 第一次循环:mid=3arr[3]=7 < 11 → 目标在右半区,更新 left=mid+1=4
  • 第二次循环:left=4right=7mid=(4+7)/2=5arr[5]=11,等于目标值 → 返回下标 5。
java 复制代码
/**
 * 二分查找标准实现(升序数组)
 * @param arr 有序的升序数组
 * @param target 需要查找的目标值
 * @return 找到则返回对应下标,找不到返回-1
 */
public static int binarySearch(int[] arr, int target) {
    // 1. 初始化左右指针
    int left = 0;
    int right = arr.length - 1;

    // 2. 核心循环:查找范围有效(左指针 <= 右指针)
    while (left <= right) {
        // 3. 计算中间下标(推荐写法,避免溢出)
        int mid = left + (right - left) / 2;
        
        // 4. 核心判断:三分法
        if (arr[mid] == target) {
            return mid; // 找到目标值,返回下标
        } else if (arr[mid] > target) {
            right = mid - 1; // 目标在左半区,缩小右边界
        } else {
            left = mid + 1; // 目标在右半区,缩小左边界
        }
    }

    // 5. 循环结束未返回,说明无目标值
    return -1;
}

// 测试代码
public static void main(String[] args) {
    int[] arr = {1,3,5,7,9,11,13,15};
    int target1 = 7;
    int target2 = 10;
    System.out.println(binarySearch(arr, target1)); // 输出:3(正确下标)
    System.out.println(binarySearch(arr, target2)); // 输出:-1(无此元素)
}

注意 :计算 mid 推荐用 left + (right-left)/2,而非 (left+right)/2

  • 问题根源:如果数组很大,leftright 都是很大的整数,left+right 会超出整数的取值范围,导致「数值溢出」,计算出错误的 mid 值;
  • 等价性:left + (right-left)/2(left+right)/2 的计算结果完全一致,只是前者能完美避免溢出问题。
  • 但在我们日常使用的数组中,很少碰见数据特别庞大的数组,这时我们使用后者来计算mid值也可以。
相关推荐
鱼跃鹰飞2 小时前
Leetcode尊享面试100题:252. 会议室
算法·leetcode·面试
爬山算法2 小时前
Hibernate(43)Hibernate中的级联删除如何实现?
java·python·hibernate
Stream_Silver2 小时前
【安装与配置Anaconda步骤,包含卸载重装】
python·conda
ai_top_trends2 小时前
AI 生成 PPT 工具横评:效率、质量、稳定性一次说清
人工智能·python·powerpoint
天天睡大觉2 小时前
Python学习9
开发语言·python·学习
2301_797312262 小时前
学习Java39天
开发语言·python·学习
曲幽2 小时前
FastAPI搭档Pydantic:从参数验证到数据转换的全链路实战
python·fastapi·web·path·field·query·pydantic·basemodel·response_model
Baihai_IDP2 小时前
如何减少单智能体输出结果的不确定性?利用并行智能体的“集体智慧”
人工智能·面试·llm
Halo_tjn2 小时前
基于Java的相关知识点
java·开发语言·windows·python·算法