1. Java基础语法概述
Java作为一门面向对象的编程语言,其基础语法构成了整个Java编程体系的根基。对于初学者而言,掌握这些基础概念就像建造房屋前需要打好地基一样重要。Java的基础语法主要包括以下几个方面:
- 程序结构:Java程序由类(class)组成,每个类包含变量和方法
- 数据类型:Java是强类型语言,所有变量都必须先声明类型后使用
- 运算符:包括算术、关系、逻辑、位运算等多种运算符
- 流程控制:if-else、switch、for、while等控制语句
- 数组:用于存储同类型数据的集合
- 注释:单行注释、多行注释和文档注释三种形式
Java程序的基本单位是类,每个Java程序至少包含一个类。最简单的Java程序如下:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }这个简单的程序展示了Java的几个基本特点:
- 类名与文件名必须一致(这里是HelloWorld.java)
- main方法是程序的入口点
- System.out.println用于输出内容到控制台
2. Java基本数据类型与变量
2.1 基本数据类型
Java有8种基本数据类型,分为4大类:
| 类型 | 数据类型 | 大小 | 取值范围 | 默认值 |
|---|---|---|---|---|
| 整型 | byte | 1字节 | -128 ~ 127 | 0 |
| short | 2字节 | -32768 ~ 32767 | 0 | |
| int | 4字节 | -2^31 ~ 2^31-1 | 0 | |
| long | 8字节 | -2^63 ~ 2^63-1 | 0L | |
| 浮点型 | float | 4字节 | 约±3.4E38(6-7位有效数字) | 0.0f |
| double | 8字节 | 约±1.7E308(15位有效数字) | 0.0d | |
| 字符型 | char | 2字节 | Unicode字符(\u0000~\uffff) | '\u0000' |
| 布尔型 | boolean | 未明确定义 | true/false | false |
注意:Java中默认的整数类型是int,如果要定义为long,需要在数值后加L或l;默认的浮点型是double,定义float需要在数值后加F或f。
2.2 变量声明与初始化
变量是存储数据的基本单元,Java中变量声明的基本语法是:
数据类型 变量名 [= 初始值];例如:
int age = 25; // 声明并初始化整型变量 double price = 99.95; // 声明并初始化双精度浮点变量 char grade = 'A'; // 声明并初始化字符变量 boolean isPass = true; // 声明并初始化布尔变量Java变量命名需要遵循以下规则:
- 由字母、数字、下划线(_)和美元符($)组成
- 不能以数字开头
- 不能是Java关键字
- 区分大小写
良好的变量命名习惯:
- 类名:首字母大写,驼峰式(如StudentInfo)
- 方法名和变量名:首字母小写,驼峰式(如getStudentName)
- 常量:全部大写,单词间用下划线连接(如MAX_VALUE)
3. Java运算符与表达式
3.1 算术运算符
Java提供基本的算术运算符:
| 运算符 | 描述 | 示例 |
|---|---|---|
| + | 加法 | a + b |
| - | 减法 | a - b |
| * | 乘法 | a * b |
| / | 除法 | a / b |
| % | 取模 | a % b |
| ++ | 自增 | a++ 或 ++a |
| -- | 自减 | a-- 或 --a |
自增/自减运算符的前置和后置区别:
int a = 5; int b = a++; // b=5, a=6(后置:先赋值再自增) int c = ++a; // c=7, a=7(前置:先自增再赋值)3.2 关系运算符
关系运算符用于比较两个值,返回布尔结果:
| 运算符 | 描述 | 示例 |
|---|---|---|
| == | 等于 | a == b |
| != | 不等于 | a != b |
| > | 大于 | a > b |
| < | 小于 | a < b |
| >= | 大于等于 | a >= b |
| <= | 小于等于 | a <= b |
3.3 逻辑运算符
逻辑运算符用于布尔表达式运算:
| 运算符 | 描述 | 示例 |
|---|---|---|
| && | 逻辑与 | a && b |
| || | 逻辑或 | a || b |
| ! | 逻辑非 | !a |
短路特性:
- 对于&&,如果左边为false,右边不再计算
- 对于||,如果左边为true,右边不再计算
3.4 赋值运算符
基本的赋值运算符是=,还有复合赋值运算符:
| 运算符 | 示例 | 等价于 |
|---|---|---|
| += | a += b | a = a + b |
| -= | a -= b | a = a - b |
| *= | a *= b | a = a * b |
| /= | a /= b | a = a / b |
| %= | a %= b | a = a % b |
3.5 位运算符
位运算符直接操作整数类型的二进制位:
| 运算符 | 描述 | 示例 |
|---|---|---|
| & | 按位与 | a & b |
| | | 按位或 | a | b |
| ^ | 按位异或 | a ^ b |
| ~ | 按位取反 | ~a |
| << | 左移 | a << b |
| >> | 右移 | a >> b |
| >>> | 无符号右移 | a >>> b |
移位运算符示例:
int a = 8; // 二进制 1000 int b = a << 2; // 左移2位,100000 = 32 int c = a >> 1; // 右移1位,100 = 44. Java流程控制
4.1 条件语句
if-else语句
基本语法:
if (条件表达式) { // 条件为true时执行的代码 } else { // 条件为false时执行的代码 }多条件判断:
if (score >= 90) { System.out.println("优秀"); } else if (score >= 80) { System.out.println("良好"); } else if (score >= 60) { System.out.println("及格"); } else { System.out.println("不及格"); }switch-case语句
适用于多分支选择:
switch (表达式) { case 值1: // 代码块1 break; case 值2: // 代码块2 break; ... default: // 默认代码块 }示例:
int day = 3; switch (day) { case 1: System.out.println("星期一"); break; case 2: System.out.println("星期二"); break; // ...其他case default: System.out.println("无效的天数"); }注意:从Java 7开始,switch支持String类型;从Java 12开始,支持更简洁的switch表达式语法。
4.2 循环结构
for循环
基本语法:
for (初始化; 条件; 迭代) { // 循环体 }示例:
// 打印1到10 for (int i = 1; i <= 10; i++) { System.out.println(i); } // 增强for循环(foreach) int[] numbers = {1, 2, 3, 4, 5}; for (int num : numbers) { System.out.println(num); }while循环
基本语法:
while (条件) { // 循环体 }示例:
int count = 0; while (count < 5) { System.out.println("Count is: " + count); count++; }do-while循环
基本语法:
do { // 循环体 } while (条件);与while的区别:do-while至少执行一次循环体
示例:
int x = 10; do { System.out.println("x = " + x); x++; } while (x < 5); // 虽然条件不满足,但会先执行一次4.3 跳转语句
- break:跳出当前循环或switch语句
- continue:跳过当前循环的剩余部分,进入下一次循环
- return:从方法中返回,可带返回值
带标签的break和continue:
outer: for (int i = 0; i < 5; i++) { inner: for (int j = 0; j < 5; j++) { if (j == 3) { break outer; // 直接跳出外层循环 } System.out.println("i=" + i + ", j=" + j); } }5. Java数组
5.1 数组声明与初始化
数组是存储同类型数据的集合,有以下几种初始化方式:
// 方式1:声明后初始化 int[] arr1; arr1 = new int[5]; // 长度为5的int数组,默认值0 // 方式2:声明时初始化 int[] arr2 = new int[]{1, 2, 3, 4, 5}; // 方式3:简写形式 int[] arr3 = {1, 2, 3, 4, 5}; // 二维数组 int[][] matrix = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };5.2 数组操作
常用数组操作:
// 获取数组长度 int length = arr3.length; // 访问数组元素 int first = arr3[0]; // 第一个元素 int last = arr3[arr3.length - 1]; // 最后一个元素 // 遍历数组 for (int i = 0; i < arr3.length; i++) { System.out.println(arr3[i]); } // 使用foreach遍历 for (int num : arr3) { System.out.println(num); } // 数组排序 Arrays.sort(arr3); // 数组复制 int[] copy = Arrays.copyOf(arr3, arr3.length);5.3 数组常见问题
数组越界:访问不存在的索引会抛出ArrayIndexOutOfBoundsException
int[] arr = new int[3]; System.out.println(arr[3]); // 错误!有效索引是0-2空指针异常:未初始化的数组变量为null,访问会抛出NullPointerException
int[] arr; System.out.println(arr[0]); // 错误!arr未初始化数组长度固定:创建后长度不可变,需要扩容时需创建新数组并复制元素
6. Java方法与参数传递
6.1 方法定义
方法的基本语法:
[修饰符] 返回类型 方法名([参数列表]) { // 方法体 [return 返回值;] }示例:
// 无返回值方法 public void printMessage(String msg) { System.out.println("消息:" + msg); } // 有返回值方法 public int add(int a, int b) { return a + b; } // 可变参数方法 public double average(int... numbers) { int sum = 0; for (int num : numbers) { sum += num; } return (double) sum / numbers.length; }6.2 方法调用
方法调用示例:
printMessage("Hello"); // 调用无返回值方法 int result = add(3, 5); // 调用有返回值方法 double avg = average(1, 2, 3, 4, 5); // 调用可变参数方法6.3 参数传递机制
Java中参数传递是值传递:
- 基本类型:传递的是值的副本
- 引用类型:传递的是引用的副本(对象地址的副本)
示例说明:
// 基本类型参数传递 void changePrimitive(int x) { x = 100; } int num = 50; changePrimitive(num); System.out.println(num); // 输出50,原始值未改变 // 引用类型参数传递 void changeReference(int[] arr) { arr[0] = 100; } int[] array = {1, 2, 3}; changeReference(array); System.out.println(array[0]); // 输出100,数组内容被修改7. Java面向对象基础
7.1 类与对象
类定义示例:
public class Person { // 字段(成员变量) private String name; private int age; // 构造方法 public Person(String name, int age) { this.name = name; this.age = age; } // 方法 public void introduce() { System.out.println("我叫" + name + ",今年" + age + "岁。"); } // Getter和Setter public String getName() { return name; } public void setName(String name) { this.name = name; } // 其他方法... }创建对象:
Person p1 = new Person("张三", 25); p1.introduce();7.2 构造方法
构造方法特点:
- 方法名与类名相同
- 没有返回类型(连void也没有)
- 可以重载(多个不同参数的构造方法)
示例:
public class Book { private String title; private String author; private double price; // 无参构造方法 public Book() { this("未知", "未知", 0.0); } // 带参构造方法 public Book(String title, String author, double price) { this.title = title; this.author = author; this.price = price; } // 其他方法... }7.3 封装与访问控制
Java提供四种访问修饰符:
| 修饰符 | 同类 | 同包 | 子类 | 不同包 |
|---|---|---|---|---|
| public | √ | √ | √ | √ |
| protected | √ | √ | √ | × |
| default | √ | √ | × | × |
| private | √ | × | × | × |
封装示例:
public class Student { private String name; // 私有字段,外部不能直接访问 private int score; // 通过公共方法访问私有字段 public String getName() { return name; } public void setName(String name) { if (name == null || name.trim().isEmpty()) { throw new IllegalArgumentException("姓名不能为空"); } this.name = name; } // 其他方法... }8. Java常用类
8.1 String类
String是不可变字符序列,常用方法:
String str = "Hello, Java!"; // 获取长度 int len = str.length(); // 字符串连接 String newStr = str.concat(" Welcome!"); // 字符串比较 boolean isEqual = str.equals("hello, java!"); // false,区分大小写 boolean isEqualIgnoreCase = str.equalsIgnoreCase("hello, java!"); // true // 子字符串 String sub = str.substring(7); // "Java!" String sub2 = str.substring(7, 11); // "Java" // 查找 int index = str.indexOf("Java"); // 7 boolean contains = str.contains("Java"); // true // 替换 String replaced = str.replace("Java", "World"); // 分割 String[] parts = "one,two,three".split(","); // 去除空格 String trimmed = " hello ".trim();8.2 StringBuilder和StringBuffer
可变字符序列,适用于频繁修改字符串的场景:
// StringBuilder(非线程安全,性能更高) StringBuilder sb = new StringBuilder(); sb.append("Hello"); sb.append(" "); sb.append("World"); String result = sb.toString(); // "Hello World" // StringBuffer(线程安全) StringBuffer sbf = new StringBuffer(); sbf.append("Java"); sbf.insert(0, "Hello "); String result2 = sbf.toString(); // "Hello Java"8.3 Math类
提供常用数学运算方法:
// 绝对值 int abs = Math.abs(-10); // 10 // 最大值/最小值 int max = Math.max(5, 10); // 10 int min = Math.min(5, 10); // 5 // 幂运算 double pow = Math.pow(2, 3); // 8.0 // 平方根 double sqrt = Math.sqrt(16); // 4.0 // 四舍五入 long round = Math.round(3.6); // 4 // 随机数 [0.0, 1.0) double random = Math.random(); // 三角函数 double sin = Math.sin(Math.PI / 2); // 1.09. Java异常处理
9.1 异常分类
Java异常体系:
- Throwable
- Error:系统错误,应用程序通常不处理(如OutOfMemoryError)
- Exception:应用程序可以处理的异常
- RuntimeException:运行时异常(如NullPointerException)
- 其他Exception:检查异常(如IOException)
9.2 try-catch-finally
基本语法:
try { // 可能抛出异常的代码 } catch (异常类型1 e) { // 处理异常类型1 } catch (异常类型2 e) { // 处理异常类型2 } finally { // 无论是否发生异常都会执行的代码 }示例:
try { int result = 10 / 0; // 抛出ArithmeticException } catch (ArithmeticException e) { System.out.println("除数不能为零: " + e.getMessage()); } finally { System.out.println("这段代码总是会执行"); }9.3 throw和throws
- throw:在方法内部抛出异常对象
- throws:在方法声明中指定可能抛出的异常类型
示例:
// 抛出异常 public void checkAge(int age) { if (age < 0) { throw new IllegalArgumentException("年龄不能为负数"); } } // 声明可能抛出的异常 public void readFile(String path) throws IOException { // 读取文件操作... }9.4 自定义异常
创建自定义异常类:
// 继承Exception或RuntimeException public class MyException extends Exception { public MyException(String message) { super(message); } public MyException(String message, Throwable cause) { super(message, cause); } } // 使用自定义异常 public void doSomething(int value) throws MyException { if (value < 0) { throw new MyException("值不能为负数"); } // 其他操作... }10. Java集合框架基础
10.1 List接口
有序、可重复的集合,常用实现类:
- ArrayList:基于动态数组,随机访问快,插入删除慢
- LinkedList:基于链表,插入删除快,随机访问慢
示例:
List<String> arrayList = new ArrayList<>(); arrayList.add("Java"); arrayList.add("Python"); arrayList.add("C++"); // 遍历 for (String lang : arrayList) { System.out.println(lang); } // 使用索引访问 String first = arrayList.get(0); List<String> linkedList = new LinkedList<>(); linkedList.add("Apple"); linkedList.add("Banana"); linkedList.addFirst("Orange"); // 在开头添加10.2 Set接口
无序、不重复的集合,常用实现类:
- HashSet:基于哈希表,无序
- LinkedHashSet:保持插入顺序
- TreeSet:基于红黑树,有序
示例:
Set<Integer> hashSet = new HashSet<>(); hashSet.add(10); hashSet.add(20); hashSet.add(10); // 重复元素不会被添加 Set<String> treeSet = new TreeSet<>(); treeSet.add("Java"); treeSet.add("Python"); treeSet.add("C++"); // 自动按字母顺序排序10.3 Map接口
键值对集合,常用实现类:
- HashMap:基于哈希表,无序
- LinkedHashMap:保持插入顺序
- TreeMap:基于红黑树,按键排序
示例:
Map<String, Integer> hashMap = new HashMap<>(); hashMap.put("Java", 20); hashMap.put("Python", 15); hashMap.put("C++", 10); // 获取值 int javaCount = hashMap.get("Java"); // 遍历 for (Map.Entry<String, Integer> entry : hashMap.entrySet()) { System.out.println(entry.getKey() + ": " + entry.getValue()); } Map<String, Integer> treeMap = new TreeMap<>(); treeMap.put("Orange", 5); treeMap.put("Apple", 10); treeMap.put("Banana", 8); // 按键字母顺序排序11. Java I/O基础
11.1 文件操作
File类示例:
File file = new File("test.txt"); // 检查文件是否存在 if (file.exists()) { System.out.println("文件大小: " + file.length() + "字节"); // 删除文件 boolean deleted = file.delete(); if (deleted) { System.out.println("文件已删除"); } } else { // 创建新文件 try { boolean created = file.createNewFile(); if (created) { System.out.println("文件创建成功"); } } catch (IOException e) { e.printStackTrace(); } }11.2 字节流
FileInputStream和FileOutputStream示例:
// 写入文件 try (FileOutputStream fos = new FileOutputStream("data.bin")) { fos.write("Hello Java".getBytes()); } catch (IOException e) { e.printStackTrace(); } // 读取文件 try (FileInputStream fis = new FileInputStream("data.bin")) { byte[] buffer = new byte[1024]; int bytesRead = fis.read(buffer); String content = new String(buffer, 0, bytesRead); System.out.println(content); } catch (IOException e) { e.printStackTrace(); }11.3 字符流
FileReader和FileWriter示例:
// 写入文件 try (FileWriter writer = new FileWriter("text.txt")) { writer.write("Hello Java\n"); writer.write("这是第二行"); } catch (IOException e) { e.printStackTrace(); } // 读取文件 try (FileReader reader = new FileReader("text.txt")) { char[] buffer = new char[1024]; int charsRead = reader.read(buffer); String content = new String(buffer, 0, charsRead); System.out.println(content); } catch (IOException e) { e.printStackTrace(); }11.4 缓冲流
BufferedReader和BufferedWriter示例:
// 写入文件(带缓冲) try (BufferedWriter bw = new BufferedWriter(new FileWriter("buffered.txt"))) { bw.write("第一行"); bw.newLine(); bw.write("第二行"); } catch (IOException e) { e.printStackTrace(); } // 读取文件(带缓冲) try (BufferedReader br = new BufferedReader(new FileReader("buffered.txt"))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); }12. Java枚举与注解
12.1 枚举类型
枚举定义示例:
public enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY } // 使用枚举 Day today = Day.MONDAY; if (today == Day.SATURDAY || today == Day.SUNDAY) { System.out.println("周末愉快!"); } else { System.out.println("工作日加油!"); }带属性的枚举:
public enum Planet { MERCURY(3.303e+23, 2.4397e6), VENUS(4.869e+24, 6.0518e6), EARTH(5.976e+24, 6.37814e6); private final double mass; // 质量(kg) private final double radius; // 半径(m) Planet(double mass, double radius) { this.mass = mass; this.radius = radius; } public double surfaceGravity() { return 6.67300E-11 * mass / (radius * radius); } }12.2 注解
Java内置常用注解:
- @Override:表示方法覆盖父类方法
- @Deprecated:表示方法已过时
- @SuppressWarnings:抑制编译器警告
自定义注解:
// 定义注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Test { String description() default ""; boolean enabled() default true; } // 使用注解 public class MyTest { @Test(description = "测试方法1", enabled = true) public void testMethod1() { // 测试代码 } @Test(enabled = false) public void testMethod2() { // 这个测试被禁用 } }13. Java泛型
13.1 泛型类
定义泛型类:
public class Box<T> { private T content; public void setContent(T content) { this.content = content; } public T getContent() { return content; } } // 使用泛型类 Box<String> stringBox = new Box<>(); stringBox.setContent("Hello"); String value = stringBox.getContent(); Box<Integer> intBox = new Box<>(); intBox.setContent(123); int num = intBox.getContent();13.2 泛型方法
定义泛型方法:
public class Util { public static <T> T getMiddle(T[] array) { return array[array.length / 2]; } } // 使用泛型方法 String[] words = {"Hello", "World", "Java"}; String middle = Util.getMiddle(words); // "World" Integer[] numbers = {1, 2, 3, 4, 5}; int midNum = Util.getMiddle(numbers); // 313.3 类型通配符
使用通配符增加灵活性:
public static double sumOfList(List<? extends Number> list) { double sum = 0.0; for (Number num : list) { sum += num.doubleValue(); } return sum; } // 可以接受List<Integer>, List<Double>等 List<Integer> ints = Arrays.asList(1, 2, 3); double sum1 = sumOfList(ints); List<Double> doubles = Arrays.asList(1.1, 2.2, 3.3); double sum2 = sumOfList(doubles);14. Java多线程基础
14.1 线程创建
继承Thread类:
class MyThread extends Thread { @Override public void run() { System.out.println("线程运行: " + getName()); } } // 创建并启动线程 MyThread thread = new MyThread(); thread.start();实现Runnable接口:
class MyRunnable implements Runnable { @Override public void run() { System.out.println("线程运行: " + Thread.currentThread().getName()); } } // 创建并启动线程 Thread thread = new Thread(new MyRunnable()); thread.start();14.2 线程同步
使用synchronized关键字:
class Counter { private int count = 0; public synchronized void increment() { count++; } public synchronized int getCount() { return count; } } // 使用 Counter counter = new Counter(); Runnable task = () -> { for (int i = 0; i < 1000; i++) { counter.increment(); } }; Thread t1 = new Thread(task); Thread t2 = new Thread(task); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("最终计数: " + counter.getCount()); // 应该是200014.3 线程间通信
使用wait()和notify():
class Message { private String message; private boolean empty = true; public synchronized String read() { while (empty) { try { wait(); } catch (InterruptedException e) {} } empty = true; notifyAll(); return message; } public synchronized void write(String message) { while (!empty) { try { wait(); } catch (InterruptedException e) {} } empty = false; this.message = message; notifyAll(); } }15. Java 8新特性
15.1 Lambda表达式
Lambda表达式示例:
// 旧方式:匿名内部类 Runnable oldRunnable = new Runnable() { @Override public void run() { System.out.println("旧方式"); } }; // Lambda方式 Runnable newRunnable = () -> System.out.println("新方式"); // 排序示例 List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); Collections.sort(names, (a, b) -> a.compareTo(b));15.2 Stream API
Stream操作示例:
List<String> words = Arrays.asList("Java", "Python", "C++", "JavaScript", "Ruby"); // 过滤和映射 List<String> filtered = words.stream() .filter(s -> s.startsWith("J")) .map(String::toUpperCase) .collect(Collectors.toList()); // 结果: ["JAVA", "JAVASCRIPT"] // 聚合操作 long count = words.stream().filter(s -> s.length() > 3).count(); Optional<String> longest = words.stream().max(Comparator.comparingInt(String::length)); // 并行流 int sum = words.parallelStream() .mapToInt(String::length) .sum();15.3 Optional类
避免NullPointerException:
Optional<String> optional = Optional.ofNullable(getString()); // 旧方式 if (optional.isPresent()) { String value = optional.get(); System.out.println(value); } // 新方式 optional.ifPresent(System.out::println); // 默认值 String result = optional.orElse("默认值"); // 链式调用 optional.map(String::toUpperCase) .filter(s -> s.length() > 3) .ifPresent(System.out::println);16. Java开发常见问题与解决方案
16.1 编码问题
解决中文乱码:
// 读取文件时指定编码 try (BufferedReader reader = new BufferedReader( new InputStreamReader(new FileInputStream("file.txt"), "UTF-8"))) { // 读取内容 } // 写入文件时指定编码 try (BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(new FileOutputStream("file.txt"), "UTF-8"))) { writer.write("中文内容"); }16.2 内存管理
避免内存泄漏:
- 及时关闭资源(使用try-with-resources)
- 注意集合类中的对象引用
- 避免静态集合长期持有对象
- 合理使用缓存,设置大小限制
示例:
// 不好的做法 public class Cache { private static final Map<String, Object> CACHE = new HashMap<>(); public static void put(String key, Object value) { CACHE.put(key, value); } // 没有移除机制,可能导致内存泄漏 } // 改进做法 public class BetterCache { private static final int MAX_SIZE = 1000; private static final Map<String, Object> CACHE = new LinkedHashMap<String, Object>(MAX_SIZE, 0.75f, true) { @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > MAX_SIZE; } }; public static synchronized void put(String key, Object value) { CACHE.put(key, value); } public static synchronized Object get(String key) { return CACHE.get(key); } }16.3 性能优化
常见性能优化技巧:
- 使用StringBuilder代替字符串拼接
- 合理使用集合类(根据场景选择ArrayList/LinkedList,HashMap/TreeMap等)
- 避免不必要的对象创建
- 使用基本类型而非包装类(如int而非Integer)
- 合理使用缓存
示例:
// 不好的做法 - 字符串拼接 String result = ""; for (int i = 0; i < 100; i++) { result += i; // 每次循环都创建新的String对象 } // 好的做法 - 使用StringBuilder StringBuilder sb = new StringBuilder(); for (int i = 0; i < 100; i++) { sb.append(i); } String result = sb.toString();16.4 并发问题
常见并发问题及解决方案:
- 竞态条件:使用同步机制(synchronized, Lock)
- 死锁:避免嵌套锁,按固定顺序获取锁
- 内存可见性:使用volatile或同步机制
- 线程安全集合:使用ConcurrentHashMap, CopyOnWriteArrayList等
示例:
// 使用ConcurrentHashMap替代同步的HashMap ConcurrentMap<String, Integer> map = new ConcurrentHashMap<>(); // 线程安全的递增操作 map.compute("counter", (k, v) -> v == null ? 1 : v + 1