14 Java 运算符的优先级

14 Java 运算符的优先级

在学习 Java 编程的过程中,理解运算符的优先级非常重要,因为运算符的优先级会直接影响表达式的计算结果。本文将详细介绍 Java 中的运算符优先级,并提供一些案例与代码实例来帮助理解。

什么是运算符优先级?

运算符优先级是指在一个表达式中,当出现多个运算符时,Java 如何决定哪些运算符先执行。优先级高的运算符会在优先级低的运算符之前执行。

Java 运算符优先级排序

以下是 Java 中运算符的优先级,从高到低排序:

  1. 后缀递增和递减: expr++expr--
  2. 前缀递增和递减: ++expr--expr+expr-expr~
  3. 乘法、除法和求余: */%
  4. 加法和减法: +-
  5. 位移: <<>>>>>
  6. 关系运算符: <><=>=
  7. 相等运算符: ==!=
  8. 按位与: &
  9. 按位异或: ^
  10. 按位或: |
  11. 逻辑与: &&
  12. 逻辑或: ||
  13. 三元运算符: ? :
  14. 赋值运算符: =+=-=*=/=%=<<=>>=&=^=|=

运算符优先级实例

示例 1:简单表达式

1
2
3
4
5
6
7
8
9
10
public class OperatorPrecedence {
public static void main(String[] args) {
int a = 5;
int b = 2;

// 注意运算符的优先级
int result = a + b * 2; // b * 2 优先执行
System.out.println(result); // 输出 9
}
}

在这个例子中,b * 2 会先执行,因为乘法的优先级高于加法。最终结果是 5 + 4,输出为 9

示例 2:使用括号改变优先级

1
2
3
4
5
6
7
8
9
10
public class OperatorPrecedence {
public static void main(String[] args) {
int a = 5;
int b = 2;

// 使用括号改变运算顺序
int result = (a + b) * 2; // (a + b) 会先执行
System.out.println(result); // 输出 14
}
}

在这个例子中,使用了括号 (a + b),这样这个表达式的计算顺序就改变了,先执行 a + b(即 5 + 2),然后将结果乘以 2,最后输出为 14

示例 3:三元运算符

1
2
3
4
5
6
7
8
9
10
public class OperatorPrecedence {
public static void main(String[] args) {
int a = 5;
int b = 10;

// 使用三元运算符
int max = (a > b) ? a : b; // 先判断 a > b
System.out.println(max); // 输出 10
}
}

在这段代码中,(a > b) 的计算会在后续赋值之前完成。因此,max 最终的值是 b 的值 10

小结

理解 Java 中运算符的优先级对于编写正确的代码至关重要。合理使用括号也能确保你的代码逻辑清晰且结果正确。通过实践和多做练习,你将更容易掌握这些运算符的优先级。

使用Executor框架管理线程

使用Executor框架管理线程

在Java中,线程的管理是一个常见且重要的任务。传统的线程管理方式通过Thread类来创建和管理线程,但这种方式可能导致代码复杂且难以维护。Java提供了Executor框架来简化线程管理,提供更强大的功能。本文将详细讲解如何使用Executor框架管理线程。

1. Executor框架概述

Executor框架是Java中用于管理和控制线程的一个重要工具。它主要包括以下几个核心接口和类:

  • Executor:一个简单的接口,用于提供执行线程的能力。
  • ExecutorService:继承自Executor,它提供了更高级的线程管理功能,如生命周期管理、任务 cancellation等。
  • ScheduledExecutorService:用于执行定时和周期性任务的服务。
  • ThreadPoolExecutor:是ExecutorService的一个具体实现,支持线程池的功能。
  • Future:表示异步计算的结果。

2. Executor的基本使用

2.1 创建ExecutorService

要使用Executor框架,首先需要创建一个ExecutorService。可以使用Executors工厂类来创建实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorExample {
public static void main(String[] args) {
// 创建一个固定大小的线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);

// 提交任务到线程池
executorService.submit(() -> {
System.out.println("Task 1 is running in " + Thread.currentThread().getName());
});

executorService.submit(() -> {
System.out.println("Task 2 is running in " + Thread.currentThread().getName());
});

// 关闭线程池
executorService.shutdown();
}
}

2.2 提交任务

使用submit方法可以将任务提交给线程池。任务可以是实现了Runnable接口或Callable接口的对象。

  • Runnable:不返回结果。
  • Callable:可以返回结果且可以抛出异常。

2.3 使用Callable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.concurrent.*;

public class CallableExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();

Future<Integer> future = executorService.submit(() -> {
// 模拟一些计算
Thread.sleep(1000);
return 123;
});

try {
// 获取结果
Integer result = future.get(); // 阻塞直到任务完成
System.out.println("Result of Callable: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
}
}

3. 线程池类型

3.1 固定大小线程池

使用Executors.newFixedThreadPool(int nThreads)可以创建一个固定大小的线程池。

3.2 可缓存线程池

使用Executors.newCachedThreadPool()可以创建一个可根据需要创建新线程的线程池。

3.3 单线程池

使用Executors.newSingleThreadExecutor()创建一个只有一个线程的线程池,确保任务按照顺序执行。

3.4 定时任务线程池

使用Executors.newScheduledThreadPool(int corePoolSize)可以创建一个支持定时和周期性任务的线程池。

4. 关闭ExecutorService

在使用完线程池后,应该调用shutdown()方法来关闭线程池。这样可以确保已经提交的任务执行完成后,线程池才会关闭。

1
executorService.shutdown();

如果需要立即停止所有正在执行的任务,可以使用shutdownNow()方法。

5. 处理线程异常

在使用ExecutorService时,如果任务抛出异常,可以通过Future.get()方法捕获ExecutionException

6. 现代使用场景——CompletableFuture

在Java 8以后的版本中,CompletableFuture提供了更为复杂的异步计算能力。它可以实现更复杂的异步任务管理和组合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
// 模拟延迟
try { Thread.sleep(1000); } catch (InterruptedException e) {}
return "Hello from CompletableFuture!";
}).thenAccept(result -> {
System.out.println(result);
});

System.out.println("Doing something else...");
}
}

小结

使用Executor框架可以有效地管理Java中的线程,简化了线程的创建和管理过程,使代码更易读、易于维护。掌握Executor框架的使用将是Java开发者必须掌握的重要技能之一。

15 Java 条件语句教程

15 Java 条件语句教程

在Java编程中,条件语句用于控制程序的执行流。通过条件判断,可以让程序在不同的情况下执行不同的代码。Java主要有以下三种条件语句:ifelseswitch

一、if语句

if语句是最基本的条件语句。它用于根据给定的条件执行某段代码。

1.1 语法结构

1
2
3
if (条件) {
// 当条件为真时执行的代码
}

1.2 实例

1
2
3
4
5
int num = 10;

if (num > 5) {
System.out.println("num大于5");
}

在这个例子中,if语句检查num是否大于5。如果条件为真,就会输出num大于5

1.3 if-else语句

if语句可以与else结合使用,以处理条件为假时的情况。

1.3.1 语法结构

1
2
3
4
5
if (条件) {
// 当条件为真时执行的代码
} else {
// 当条件为假时执行的代码
}

1.3.2 实例

1
2
3
4
5
6
7
int num = 3;

if (num > 5) {
System.out.println("num大于5");
} else {
System.out.println("num不大于5");
}

在这个例子中,由于num不大于5,所以程序输出num不大于5

1.4 else if语句

当有多个条件需要判断时,可以使用else if来创建多个条件分支。

1.4.1 语法结构

1
2
3
4
5
6
7
if (条件1) {
// 条件1为真时执行的代码
} else if (条件2) {
// 条件2为真时执行的代码
} else {
// 条件1和条件2都为假时执行的代码
}

1.4.2 实例

1
2
3
4
5
6
7
8
9
int num = 5;

if (num > 5) {
System.out.println("num大于5");
} else if (num == 5) {
System.out.println("num等于5");
} else {
System.out.println("num小于5");
}

这个例子中,程序输出num等于5,因为num的值正好为5。

二、switch语句

switch语句是一种多条件的选择语句,通常用于当你需要根据一个变量的值来选择多个执行路径时。

2.1 语法结构

1
2
3
4
5
6
7
8
9
10
11
switch (表达式) {
case 常量1:
// 执行代码块1
break;
case 常量2:
// 执行代码块2
break;
// 可以有任意数量的case
default:
// 可选的默认代码块
}

2.2 实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int day = 3;

switch (day) {
case 1:
System.out.println("今天是星期一");
break;
case 2:
System.out.println("今天是星期二");
break;
case 3:
System.out.println("今天是星期三");
break;
default:
System.out.println("输入的日期无效");
}

在这个例子中,基于day的值,程序会输出今天是星期三

2.3 注意事项

  1. 每个case标签后使用break语句,以防止程序继续执行后面的case
  2. 可以通过default标签提供一个默认的处理方式。
  3. switch语句的表达式可以是intcharbyteshortString等类型。

小结

在Java中,ifswitch都是用于条件判断的强大工具。if语句适用于更复杂的条件判断,而switch语句在特定情况下(如固定的值判断)能够提高代码的可读性和清晰度。你可以根据具体的需求选择合适的条件语句来优化你的代码逻辑。