第4篇:Java数组与字符串:从基础用法到面试高频考点

上一篇我们掌握了Java流程控制,能通过分支和循环实现复杂逻辑(比如打印九九乘法表、金字塔),但这些案例中,我们只能处理单个变量的数据。实际开发中,我们经常需要存储"多个相同类型的数据"(比如一个班级50名学生的成绩、一组商品的价格),或者"处理文本信息"(比如用户输入的姓名、密码),这就需要用到Java中的数组字符串

数组是存储多个相同类型数据的"容器",字符串是处理文本信息的核心工具,二者都是Java基础中高频使用、高频面试的知识点。本篇文章将从基础入手,手把手教你掌握数组的定义、初始化、遍历方式,String类的核心常用方法,拆解新手高频易错点(比如数组越界、字符串不可变),同时讲解面试中常见的数组与字符串问题,让你不仅会用,还能吃透底层逻辑,为后续学习集合、面向对象进阶筑牢基础。

核心目标:掌握数组的定义、初始化、遍历(普通for、增强for)和常见操作,熟练运用String类的核心方法(拼接、截取、替换、判断等),理解字符串不可变特性,能独立完成数组排序、字符串处理等实战案例,规避常见坑,掌握基础面试考点。

一、前置认知:数组与字符串的核心作用

在学习具体用法之前,我们先搞清楚:为什么需要数组和字符串?它们能解决什么问题?

  1. 数组的作用:存储多个相同类型的数据,避免重复定义变量。比如存储5名学生的成绩,不用定义score1、score2、score3、score4、score5,只需定义一个数组,就能存储所有成绩,且方便统一操作(比如遍历所有成绩、求平均分);

  2. 字符串的作用:处理文本信息,Java中用String类封装文本,提供了大量便捷方法,比如判断两个文本是否相等、截取文本、替换文本等,无需我们自己编写复杂逻辑。

核心结论:数组解决"多个相同类型数据存储"的问题,字符串解决"文本处理"的问题,二者是Java开发中最基础、最常用的工具,几乎所有程序都会用到。

二、Java数组:存储多个相同类型数据的容器

数组的核心特点:固定长度、相同类型、连续存储。一旦数组初始化完成,长度就不能修改;数组中所有元素的类型必须一致(比如int数组只能存整数,String数组只能存字符串);数组元素在内存中是连续存储的,访问效率高。

2.1 数组的定义与初始化(3种常用方式)

数组的定义有两种格式,初始化分为"静态初始化"和"动态初始化",新手重点掌握前两种初始化方式,根据场景选择使用。

(1)数组的定义格式(两种,任选其一)
java 复制代码
// 格式1:数据类型[] 数组名;(推荐,更规范,一眼能看出是数组)
int[] scores;  // 定义一个int类型的数组,用于存储成绩
String[] names;  // 定义一个String类型的数组,用于存储姓名

// 格式2:数据类型 数组名[];(兼容C/C++语法,不推荐)
int scores[];
String names[];

注意:仅定义数组,不会分配内存空间,数组名只是一个"引用",必须初始化后才能使用(否则会报错)。

(2)静态初始化:明确指定数组元素,长度由元素个数自动决定

语法格式:

java 复制代码
// 格式1:完整写法
数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, 元素3, ...};

// 格式2:简化写法(推荐,简洁)
数据类型[] 数组名 = {元素1, 元素2, 元素3, ...};

核心特点:初始化时,直接指定数组中的每一个元素,数组长度 = 元素个数,无需手动指定长度。

实战案例:

java 复制代码
public class ArrayInit1 {
    public static void main(String[] args) {
        // 静态初始化:存储5名学生的成绩(int类型)
        int[] scores = {90, 85, 95, 78, 88};
        // 静态初始化:存储3个姓名(String类型)
        String[] names = new String[]{"张三", "李四", "王五"};
        
        // 打印数组(直接打印数组名,输出的是数组的内存地址,不是元素)
        System.out.println(scores);  // 输出:[I@7c30a502([I表示int数组,后面是内存地址)
        System.out.println(names);   // 输出:[Ljava.lang.String;@49e4cb85
    }
}

避坑点1:静态初始化的简化写法({元素1, 元素2}),只能在定义数组时使用,不能先定义再赋值。比如"int[] scores; scores = {90,85};"是错误的,正确写法是"int[] scores = {90,85};"或"scores = new int[]{90,85};"。

(3)动态初始化:明确指定数组长度,元素由系统赋默认值

语法格式:

java 复制代码
数据类型[] 数组名 = new 数据类型[数组长度];

核心特点:初始化时,只指定数组长度,不指定具体元素,系统会给数组中每一个元素赋"默认值"(和基本数据类型的默认值一致),后续再手动给元素赋值。

数组元素的默认值(重点,和第2篇基本数据类型默认值一致):

  • 整数类型(int、long、byte、short):默认值0;

  • 浮点类型(double、float):默认值0.0;

  • 字符类型(char):默认值'\u0000'(空字符,不可见);

  • 布尔类型(boolean):默认值false;

  • 引用类型(String、数组等):默认值null(表示空引用,没有指向任何对象)。

实战案例:

java 复制代码
public class ArrayInit2 {
    public static void main(String[] args) {
        // 动态初始化:定义一个长度为5的int数组(存储成绩),元素默认值0
        int[] scores = new int[5];
        // 动态初始化:定义一个长度为3的String数组(存储姓名),元素默认值null
        String[] names = new String[3];
        
        // 手动给数组元素赋值(数组索引从0开始)
        scores[0] = 90;  // 给第1个元素赋值(索引0)
        scores[1] = 85;  // 给第2个元素赋值(索引1)
        scores[2] = 95;
        scores[3] = 78;
        scores[4] = 88;
        
        names[0] = "张三";
        names[1] = "李四";
        names[2] = "王五";
        
        // 打印数组元素(通过索引访问)
        System.out.println(scores[0]);  // 输出90
        System.out.println(names[2]);  // 输出王五
    }
}

避坑点2:数组的索引从0开始,不是从1开始!比如长度为5的数组,索引范围是0~4,访问索引5会报"数组越界异常"(新手最易犯)。

2.2 数组的核心操作:访问、遍历、修改(重点)

数组的核心操作围绕"索引"展开,通过索引可以访问、修改数组元素;遍历是数组最常用的操作(遍历所有元素,进行查询、计算等)。

(1)数组元素的访问与修改

语法格式:

java 复制代码
// 访问数组元素:数组名[索引]
数组名[索引];

// 修改数组元素:数组名[索引] = 新值;
数组名[索引] = 新值;

实战案例:

java 复制代码
public class ArrayOperate1 {
    public static void main(String[] args) {
        int[] scores = {90, 85, 95, 78, 88};
        
        // 访问元素:获取索引2的元素(第3个元素)
        int score = scores[2];
        System.out.println("索引2的元素:" + score);  // 输出95
        
        // 修改元素:将索引3的元素(78)修改为80
        scores[3] = 80;
        System.out.println("修改后索引3的元素:" + scores[3]);  // 输出80
        
        // 错误示例:数组越界(长度为5,索引最大是4,访问索引5报错)
        // System.out.println(scores[5]);  // 报错:ArrayIndexOutOfBoundsException
    }
}

重点提醒:数组越界异常(ArrayIndexOutOfBoundsException)是新手最常遇到的异常之一,原因是访问的索引超出了数组的索引范围(0 ~ 数组长度-1),务必注意!

(2)数组的遍历(3种方式,重点掌握前两种)

遍历:依次访问数组中的每一个元素,常用场景:打印所有元素、求总和、求平均值、找最大值/最小值等。

方式1:普通for循环(最灵活,可获取索引,适合需要修改元素的场景)

java 复制代码
public class ArrayTraverse1 {
    public static void main(String[] args) {
        int[] scores = {90, 85, 95, 80, 88};
        // 普通for循环:i从0到数组长度-1(scores.length获取数组长度)
        for (int i = 0; i < scores.length; i++) {
            System.out.println("索引" + i + "的元素:" + scores[i]);
        }
        
        // 实战:求成绩总和和平均值
        int sum = 0;
        for (int i = 0; i < scores.length; i++) {
            sum += scores[i];  // 累加所有元素
        }
        double avg = sum / (double) scores.length;  // 强转为double,避免整数除法
        System.out.println("成绩总和:" + sum);
        System.out.println("成绩平均值:" + avg);
    }
}

说明:数组名.length 可以获取数组的长度(固定值,初始化后不变),无需手动记录长度,避免出错。

方式2:增强for循环(foreach循环,简洁,适合仅遍历、不修改元素的场景)

语法格式:

java 复制代码
for (数据类型 变量名 : 数组名) {
    // 变量名表示数组中的当前元素,依次遍历每一个元素
}

实战案例:

java 复制代码
public class ArrayTraverse2 {
    public static void main(String[] args) {
        String[] names = {"张三", "李四", "王五", "赵六"};
        // 增强for循环:依次遍历names数组中的每一个元素,赋值给name变量
        for (String name : names) {
            System.out.println("姓名:" + name);
        }
        
        // 注意:增强for循环无法修改数组元素(变量name是临时变量,修改它不影响原数组)
        for (int score : scores) {
            score = 100;  // 无效,原数组元素不会改变
        }
    }
}

避坑点3:增强for循环只能遍历元素,无法修改原数组元素(临时变量不影响原数组);如果需要修改元素,必须用普通for循环(通过索引修改)。

方式3:Arrays.toString()方法(快速打印数组,适合调试)

Java提供了Arrays工具类(需要导入import java.util.Arrays;),其中toString()方法可以快速将数组转为字符串,直接打印所有元素,无需手动遍历。

java 复制代码
import java.util.Arrays;

public class ArrayTraverse3 {
    public static void main(String[] args) {
        int[] scores = {90, 85, 95, 80, 88};
        String[] names = {"张三", "李四", "王五"};
        
        // 快速打印数组,格式:[元素1, 元素2, 元素3]
        System.out.println(Arrays.toString(scores));  // 输出:[90, 85, 95, 80, 88]
        System.out.println(Arrays.toString(names));   // 输出:[张三, 李四, 王五]
    }
}

2.3 数组的常见实战案例

结合数组的遍历和修改,完成3个经典实战案例,巩固数组用法。

案例1:找出数组中的最大值和最小值

java 复制代码
public class ArrayCase1 {
    public static void main(String[] args) {
        int[] nums = {15, 28, 9, 36, 22, 10};
        // 假设第一个元素是最大值和最小值
        int max = nums[0];
        int min = nums[0];
        
        // 遍历数组,更新最大值和最小值
        for (int num : nums) {
            if (num > max) {
                max = num;  // 找到更大的值,更新max
            }
            if (num < min) {
                min = num;  // 找到更小的值,更新min
            }
        }
        
        System.out.println("数组中的最大值:" + max);  // 输出36
        System.out.println("数组中的最小值:" + min);  // 输出9
    }
}

案例2:数组排序(使用Arrays.sort()方法,常用)

java 复制代码
import java.util.Arrays;

public class ArrayCase2 {
    public static void main(String[] args) {
        int[] nums = {15, 28, 9, 36, 22, 10};
        System.out.println("排序前:" + Arrays.toString(nums));
        
        // 调用Arrays.sort()方法,对数组进行升序排序(从小到大)
        Arrays.sort(nums);
        
        System.out.println("排序后:" + Arrays.toString(nums));  // 输出:[9, 10, 15, 22, 28, 36]
    }
}

说明:Arrays.sort()方法默认是升序排序,如果需要降序排序,后续会讲解(需要结合其他方法,新手先掌握升序即可)。

案例3:数组复制(从一个数组复制到另一个数组)

java 复制代码
import java.util.Arrays;

public class ArrayCase3 {
    public static void main(String[] args) {
        int[] srcArr = {10, 20, 30, 40, 50};  // 原数组
        int[] destArr = new int[5];  // 目标数组(长度和原数组一致)
        
        // 方式1:循环复制(手动复制,灵活)
        for (int i = 0; i < srcArr.length; i++) {
            destArr[i] = srcArr[i];
        }
        System.out.println("循环复制后:" + Arrays.toString(destArr));
        
        // 方式2:Arrays.copyOf()方法(推荐,简洁)
        int[] destArr2 = Arrays.copyOf(srcArr, srcArr.length);
        System.out.println("copyOf复制后:" + Arrays.toString(destArr2));
    }
}

2.4 数组的常见易错点(新手必看)

  1. 数组越界异常:访问的索引超出0~数组长度-1的范围,比如长度为5的数组,访问索引5;

  2. 静态初始化简化写法使用错误:先定义数组,再用{元素}赋值(比如int[] arr; arr = {1,2,3}; 错误);

  3. 增强for循环修改数组元素:误以为修改临时变量能改变原数组,实际无效;

  4. 数组长度修改错误:试图修改数组的length属性(比如arr.length = 10; 错误),数组长度一旦初始化就固定,无法修改;

  5. 空指针异常:数组未初始化(仅定义,未赋值),就访问数组元素(比如int[] arr; System.out.println(arr[0]); 错误)。

三、Java字符串:处理文本信息的核心工具

Java中,字符串用String类表示,String是一个引用类型(不是基本数据类型),用于封装文本信息。String类提供了大量便捷的方法,能快速实现字符串的拼接、截取、替换、判断等操作,是Java开发中最常用的类之一。

核心注意点:String类是不可变的(字符串一旦创建,内容就不能修改),这是String类的核心特性,也是新手容易踩坑的点,后续会详细讲解。

3.1 字符串的定义与初始化(3种常用方式)

字符串的初始化有3种方式,重点掌握前两种,理解"直接赋值"和"new关键字创建"的区别(面试高频考点)。

(1)方式1:直接赋值(推荐,简洁,会复用字符串常量池中的对象)
java 复制代码
String 变量名 = "字符串内容";

// 示例
String name = "张三";
String message = "Hello Java!";

核心原理(面试考点):Java中有一个"字符串常量池"(内存中的一块区域),当用直接赋值方式创建字符串时,会先检查常量池中是否存在该字符串:如果存在,直接引用;如果不存在,创建一个新的字符串存入常量池,再引用。这样可以节省内存,避免重复创建相同的字符串。

(2)方式2:new关键字创建(不推荐,会创建新对象,不复用常量池)
java 复制代码
String 变量名 = new String("字符串内容");

// 示例
String name = new String("张三");
String message = new String("Hello Java!");

核心原理(面试考点):用new关键字创建字符串时,无论常量池中是否存在该字符串,都会在内存中创建一个新的String对象,然后将对象的引用赋值给变量,不会复用常量池中的对象,会占用更多内存。

(3)方式3:通过字符数组创建(了解即可)
java 复制代码
char[] chars = {'H', 'e', 'l', 'l', 'o'};
String message = new String(chars);  // 将字符数组转为字符串
System.out.println(message);  // 输出:Hello
面试题:String s1 = "abc"; 和 String s2 = new String("abc"); 的区别?

答案:

  • s1:直接赋值,先检查字符串常量池,若没有"abc",则在常量池中创建"abc",s1引用常量池中的对象;若有,直接引用,只创建1个对象(常量池中的对象);

  • s2:new关键字创建,无论常量池中是否有"abc",都会在内存中创建一个新的String对象,s2引用这个新对象,最多创建2个对象(常量池中的"abc"和新创建的对象)。

实战验证:

java 复制代码
public class StringDemo1 {
    public static void main(String[] args) {
        String s1 = "abc";
        String s2 = "abc";
        String s3 = new String("abc");
        String s4 = new String("abc");
        
        // == 比较的是对象的内存地址(引用地址)
        System.out.println(s1 == s2);  // true(s1和s2引用常量池中的同一个对象)
        System.out.println(s3 == s4);  // false(s3和s4引用两个不同的对象)
        System.out.println(s1 == s3);  // false(s1引用常量池,s3引用新对象)
        
        // equals() 比较的是字符串的内容(推荐用于字符串比较)
        System.out.println(s1.equals(s2));  // true(内容相同)
        System.out.println(s3.equals(s4));  // true(内容相同)
        System.out.println(s1.equals(s3));  // true(内容相同)
    }
}

避坑点4:比较两个字符串的内容,必须用equals()方法,不能用"==";"=="比较的是两个字符串的引用地址(是否是同一个对象),不是内容。​

3.2 String类核心常用方法(重点,必须掌握)​

String类提供了大量方法,新手重点掌握以下10个常用方法,能满足日常开发中的大部分需求,结合案例理解用法。​

|----------|-----------|---------|---------|
| ​ 方法名​ ​ | ​ 方法作用​ ​ | ​ 示例​ ​ | ​ 结果​ ​ |

|------------------------------------------|-----------------------------|------------------------------------|-------------------|
| ​ length()​ ​ | ​ 获取字符串的长度(字符个数)​ ​ | ​ "Hello".length()​ ​ | ​ 5​ ​ |
| ​ equals(String str)​ ​ | ​ 比较两个字符串的内容是否相同(区分大小写)​ ​ | ​ "abc".equals("ABC")​ ​ | ​ false​ ​ |
| ​ equalsIgnoreCase(String str)​ ​ | ​ 比较两个字符串的内容是否相同(不区分大小写)​ ​ | ​ "abc".equalsIgnoreCase("ABC")​ ​ | ​ true​ ​ |
| ​ concat(String str)​ ​ | ​ 拼接两个字符串(等价于"+")​ ​ | ​ "Hello".concat(" Java")​ ​ | ​ "Hello Java"​ ​ |
| ​ charAt(int index)​ ​ | ​ 获取指定索引位置的字符(索引从0开始)​ ​ | ​ "Hello".charAt(1)​ ​ | ​ 'e'​ ​ |
| ​ ​ | ​ ​ | ​ ​ | ​ ​ |
| ​ ​ | ​ ​ | ​ ​ | ​ ​ |
| ​ replace(char oldChar, char newChar)​ ​ | ​ 替换字符串中的指定字符​ ​ | ​ "Hello".replace('l','x')​ ​ | ​ "Hexxo"​ ​ |
| ​ isEmpty()​ ​ | ​ 判断字符串是否为空(长度为0)​ ​ | ​ "".isEmpty()​ ​ | ​ true​ ​ |
| ​ trim()​ ​ | ​ 去除字符串前后的空格(不去除中间的空格)​ ​ | ​ " Hello Java ".trim()​ ​ | ​ "Hello Java"​ ​ |

实战演示(常用方法综合运用)

java 复制代码
public class StringMethodDemo {
    public static void main(String[] args) {
        String str = "  Hello Java!  ";
        
        // 1. 获取字符串长度
        System.out.println("字符串长度:" + str.length());  // 输出14(包含前后空格)
        
        // 2. 去除前后空格
        String str2 = str.trim();
        System.out.println("去除空格后:" + str2);  // 输出:Hello Java!
        System.out.println("去除空格后长度:" + str2.length());  // 输出11
        
        // 3. 拼接字符串
        String str3 = str2.concat(" 你好!");
        System.out.println("拼接后:" + str3);  // 输出:Hello Java! 你好!
        
        // 4. 截取字符串(从索引6开始,截取到末尾)
        String str4 = str2.substring(6);
        System.out.println("截取后:" + str4);  // 输出:Java!
        
        // 5. 替换字符
        String str5 = str2.replace('J', 'j');
        System.out.println("替换后:" + str5);  // 输出:Hello java!
        
        // 6. 比较字符串
        String str6 = "Hello Java!";
        System.out.println(str2.equals(str6));  // true(内容相同)
        System.out.println(str2.equalsIgnoreCase("hello java!"));  // true(不区分大小写)
        
        // 7. 获取指定索引的字符
        char c = str2.charAt(0);
        System.out.println("索引0的字符:" + c);  // 输出:H
    }
}

3.3 String不可变特性(核心考点,必懂)

String类的核心特性:不可变,即字符串一旦创建,其内容就不能被修改。我们平时写的"字符串修改"(比如拼接、替换),并不是修改原字符串的内容,而是创建了一个新的字符串对象,原字符串的内容依然不变。

实战演示(理解不可变):

java 复制代码
public class StringImmutable {
    public static void main(String[] args) {
        String s = "Hello";
        // 看似修改字符串,实际是创建了一个新的字符串对象
        s = s.concat(" Java");  // 拼接后,创建新对象"Hello Java",s引用新对象
        System.out.println(s);  // 输出:Hello Java
        
        // 原字符串"Hello"依然存在于常量池中,没有被修改
        String s2 = "Hello";
        System.out.println(s2);  // 输出:Hello(原字符串未变)
    }
}

四、数组与字符串的综合实战

结合数组和字符串的知识点,完成一个综合实战案例,提升代码综合运用能力。

案例:存储5名学生的姓名和成绩,完成以下操作:1. 录入学生信息;2. 打印所有学生信息;3. 求平均成绩;4. 找出成绩最高的学生;5. 查找指定姓名的学生成绩。

java 复制代码
import java.util.Arrays;
import java.util.Scanner;

public class ArrayStringDemo {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int count = 5;  // 学生人数
        
        // 定义数组:存储学生姓名(String数组)和成绩(int数组)
        String[] names = new String[count];
        int[] scores = new int[count];
        
        // 1. 录入学生信息
        for (int i = 0; i < count; i++) {
            System.out.print("请输入第" + (i+1) + "名学生的姓名:");
            names[i] = scanner.next();
            System.out.print("请输入第" + (i+1) + "名学生的成绩:");
            scores[i] = scanner.nextInt();
        }
        
        // 2. 打印所有学生信息
        System.out.println("\n所有学生信息:");
        for (int i = 0; i < count; i++) {
            System.out.println("姓名:" + names[i] + ",成绩:" + scores[i]);
        }
        
        // 3. 求平均成绩
        int sum = 0;
        for (int score : scores) {
            sum += score;
        }
        double avg = sum / (double) count;
        System.out.println("\n平均成绩:" + avg);
        
        // 4. 找出成绩最高的学生
        int maxScore = scores[0];
        String maxName = names[0];
        for (int i = 1; i < count; i++) {
            if (scores[i] > maxScore) {
                maxScore = scores[i];
                maxName = names[i];
            }
        }
        System.out.println("成绩最高的学生:" + maxName + ",成绩:" + maxScore);
        
        // 5. 查找指定姓名的学生成绩
        System.out.print("\n请输入要查找的学生姓名:");
        String searchName = scanner.next();
        boolean found = false;
        for (int i = 0; i < count; i++) {
            // 用equals()方法比较字符串(姓名)
            if (names[i].equals(searchName)) {
                System.out.println(searchName + "的成绩是:" + scores[i]);
                found = true;
                break;
            }
        }
        if (!found) {
            System.out.println("未找到姓名为" + searchName + "的学生");
        }
        
        scanner.close();
    }
}

运行效果:

java 复制代码
请输入第1名学生的姓名:张三
请输入第1名学生的成绩:90
请输入第2名学生的姓名:李四
请输入第2名学生的成绩:85
请输入第3名学生的姓名:王五
请输入第3名学生的成绩:95
请输入第4名学生的姓名:赵六
请输入第4名学生的成绩:78
请输入第5名学生的姓名:孙七
请输入第5名学生的成绩:88

所有学生信息:
姓名:张三,成绩:90
姓名:李四,成绩:85
姓名:王五,成绩:95
姓名:赵六,成绩:78
姓名:孙七,成绩:88

平均成绩:87.2
成绩最高的学生:王五,成绩:95

请输入要查找的学生姓名:李四
李四的成绩是:85

五、新手高频易错点总结(必看,避坑指南)

  1. 数组相关:数组越界、静态初始化简化写法错误、增强for循环修改元素无效、数组长度修改错误;

  2. 字符串相关:用"=="比较内容、忽略字符串不可变特性、索引越界、trim()方法误用、空指针异常;

  3. 综合易错:数组和字符串的索引都是从0开始,忘记这一点导致频繁报错;

  4. 面试易错:String直接赋值和new关键字创建的区别、String不可变的原理。

六、总结与下期预告

本篇文章重点讲解了Java数组与字符串的核心知识点:数组的定义、初始化、遍历和常见操作,String类的定义、常用方法和不可变特性,同时结合多个实战案例(数组排序、字符串回文判断、学生信息管理),拆解了新手高频易错点和面试高频考点,让你不仅会用,还能理解底层逻辑。

相关推荐
俺爱吃萝卜2 小时前
Spring Boot 3 + JDK 17:新一代微服务架构最佳实践
java·spring boot·架构
曹牧2 小时前
Spring :component-scan
java·后端·spring
下地种菜小叶2 小时前
定时任务系统怎么设计?一次讲清任务注册、分布式调度、幂等执行与失败补偿
java·开发语言·数据库·oracle·rabbitmq
做个文艺程序员2 小时前
Spring Boot 项目集成 OpenClAW【OpenClAW + Spring Boot 系列 第1篇】
java·人工智能·spring boot·开源
withelios2 小时前
Java泛型全面理解指南
java
withelios2 小时前
Java枚举全解析:从基础到高级使用技巧
java·后端
yngsqq2 小时前
编译的dll自动复制到指定目录并重命名
java·服务器·前端
曹牧2 小时前
Spring:@RequestMapping
java·后端·spring
霸道流氓气质3 小时前
SpringBoot+LangChain4j+Ollama实现本地大模型语言LLM的搭建、集成和示例流程
java·spring boot·后端