2.2.1 if条件语句

if条件语句是一个重要的编程语句,用于告诉程序在某个条件成立的情况下执行某段语句,而在另一种情况下执行另外的语句。

使用if条件语句,可选择是否要执行紧跟在条·件之后的那个语句。关键字if之后是作为条件的”布尔表达式”。如果该表达式返回的结果为true,则执行其后的语句;如果为false,则不执行if条件之后的语句。if条件语句可分为简单的if条件语句、if…else语句和if…else if多分支语句。

1.简单的if条件语句

语法如下

1
2
3
if(布尔表达式){
语句序列
}

*布尔表达式:必要参数,表示最后返回的结果必须是一个布尔值。它可以是一个单纯的布尔变量或常量,也可以是使用关系或布尔运算符的表达式

*语句序列:可选参数。可以是一条或多条语句,当表达式的值为true时执行这些语句。若语句序列中仅有一条语句,则可以省略条件语句中的“{}”。

如果语句序列中只有一条语句,可以采用以下写法:

1
2
3
int a = 100;
if(a == 100)
System.out.println("a的值是100");

过程如下:

image-20240509211626560

【例2.1】判断手机号码是否存在

创建TP类,模拟拨打电话场景,如果电话号码不是84972266,则提示拨打号码不存在。

1
2
3
4
5
6
7
8
public class TP{
public static void main(String[] args){
int Number = 123456789;
if(Number != 84972266){
System.out.prinyln("对不起,您拨打的号码不存在!");
}
}
}

2.if···else语句

if···else语句是条件语句中最常用的一种形式,它会针对某种条件有选择地做出处理。通常表现为“如果满足某种条件,就进行某种处理,否则就进行另一种处理”。语法如下:

1
2
3
4
5
if(条件表达式){
语法序列1
}else{
语句序列2
}

if后面”( )”内的表达式的值必须是boolean型的。如果表达式的值为true,则执行紧跟if语句的复合语句;如果表达式的值为false,则执行else后面的复合语句。过程如下

image-20240509211652957

【例2.2】使用if···else语句校验密码

在项目中创建Login类,在主方法中定义变量,并通过使用if···else语句判断变量的值来决定输出结果。

1
2
3
4
5
6
7
8
9
10
public class Login{
public static void main(String[] args){
int password = 987654321;
if(123456789 == password){
System.out.println("密码正确,欢迎登录");
}else{
System.out.println("密码错误,拒绝登录");
}
}
}

3.if…else if多分支语句

if…else if 多分支语句用于针对某一事件的多种情况进行处理。通常表现为“如果满足某种条件,就进行某种处理,否则如果满足另一种条件则执行另一种处理”。语法如下

1
2
3
4
5
6
7
8
9
if(条件表达式1){
语句序列1
}else if(条件表达式2){
语句序列2
}
...
else if(条件表达式n){
语句序列n
}

执行过程如图所示

image-20240512161207307

【例2.3】使用if…else if语句实现饭店座位分配

创建rest类,声明整型变量count表示用餐人数,根据人数安排客人到4人桌,8人桌或包厢用餐

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class rest{
public static void main(String args[]){
System.out.println("欢迎光临,请问有多少人用餐?");
int count = 9
System.out.println("回答:"+count+"人");
if(count<=4){
System.out.println("客人请到大厅4人桌用餐");
}else if(count>4&&count<=16){
System.out.println("客人请到大厅8人桌用餐");
}else if(count>8&&count<=16){
System.out.println("客人请到楼上包厢用餐");
}else{
System.out.println("抱歉,我们店暂时没有这么大的包厢!");
}
}
}

2.2.2 Switch多分支语句

在编程中,一个常见的问题就是检测一个变量是否符合某个条件。如果不符合,再用另外一个值来检测,以此类推。当然用if条件语句也可以完成。

例如,使用if语句对考试成绩进行评估,关键代码如下:

1
2
3
4
5
6
if(grade == 'A'){
System.out.println("真棒");
}
if(grade == 'B'){
System.out.println("做的不错");
}

在Java中,可以用Switch语句将动作组织起来,以一个比较简单明了的方式来实现“多选一”的选择。语法如下:

1
2
3
4
5
6
7
8
9
10
11
12
switch(表达式){
case 常量值1
语句块1
[break;]
...
case 常量值n:
语句块n
[break;]
default:
语句块n+1;
[break;]
}

switch语句中表达式的值必须是整型、字符型、字符串类型或枚举类型,常量值1~n的数据类型必须与表达式的值的类型相同。

switch语句首先计算表达式的值,如果表达式的计算结果和某个case后面的常量值相同,则执行该case语句后的若干个语句直到遇到break语句为止。此时,如果该case语句中没有break语句,将继续执行后面case中的若干个语句,直到遇到break语句为止。若没有一个常量的值与表达式的值相同,则执行default后面的语句。default语句为可选的,如果它不存在,且switch语句中表达式的值不与任何case的常量值相同,switch语句则不做任何处理。

image-20240512163659523

注意
(1)同一个switch语句,case的常量值必须互不相同。
(2)在switch语句中,case语句后常量表达式的值可以为整数,但绝不可以是非整数的实数。例如,下面的代码就是错误的:

【例2.4】使用switch语句分为考试分数分级

创建Grade类,使用Scanner类在控制台输入分数,然后用switch多分支语句判断输入的分数属于哪类成绩。10分和9分属于优,8分属于良,7分和6分属于中,5分、4分、3分、2分、1分以及0分均属于差。

image-20240512165633843

Java多线程基础

等待和唤醒

wait() 线程等待,等待的过程中,释放锁,需要其他线程调用notify去唤醒

notify()唤醒一个等待的线程,如果有多个线程等待,则随机一条唤醒

notifyAll() 唤醒所有等待的线程

Lock锁

是一个接口

使用

获取 其 实现类 ReentrantLock

方法

lock()获取锁

unlock()释放锁

synchronized 与lock的区别

synchronized:不管是同步代码块还是同步方法,都需要在结束一对{}之后,释放锁对象

Lock:是通过两个方法控制需要被同步的代码,更灵活(两个方法为lock和unlock)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class MyTicket implements Runnable {
int ticket = 100;
Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
try {
Thread.sleep(100L);
lock.lock();
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + \"买了第\" + ticket + \"张票\");
ticket--;
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}finally {
lock.unlock();
}
}
}
}

public class Test01 {
public static void main(String[] args) {
MyTicket myTicket = new MyTicket();

Thread t1 = new Thread(myTicket, "张三");
Thread t2 = new Thread(myTicket, "李四");
Thread t3 = new Thread(myTicket, "王五");

t1.start();
t2.start();
t3.start();

}

}

Callable

接口,实现多线程的一种方式

Callable是一个接口,类似于Runnable

方法

1.V call() 设置线程任务,类似于run()方法,与之不同的是call可以throw异常,并且还有返回值

2.call方法和run方法的区别:

a.相同点:都是设置线程任务的

b.不同点:

(1)call方法有返回值,而且有异常可以throws

(2)run方法没有返回值,而且有异常不可以throws

3.内容

a.是一个泛型接口。

b.泛型:用于指定我们操作什么类型的数据,<>中只能写引用数据类型,如果泛型不写,默认是Object类型数据。

c.实现Callable接口时,指定泛型是什么类型的,重写的call方法返回值就是什么类型的。

4.获取call方法返回值: FutureTask<V>

a. FutureTask<V> 实现了一个接口: Future <V>

b. FutureTask<V>中有一个方法:

5.V get() -> 获取call方法的返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "ssssss";
}
}
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable myCallable = new MyCallable();
FutureTask<String> futureTask = new FutureTask<>(myCallable);
Thread t1 = new Thread(futureTask);
t1.start();
System.out.println(futureTask.get());
}
}

线程池

容器中有多条线程对象,来了线程任务,直接线程池中获取线程对象,用完还回去。

获取
1
static ExecutorService newFixedThreadPool(int nThreads)
执行线程任务

Futhre<?> submit(Runnable task) 提交一个Runnable任务用于执行

Future<T> submit(Callable<T> task) 提交一个Callable任务用于执行

返回值接口Futher

用于接收run方法或者call方法返回值的,但是run方法没有返回值,所以可以不用Future接收,执行call方法需要用Future接收

Future中有一个方法:V get() 用于获取call方法返回值

关闭

ExecutorService中的方法:

\nvoid shutdown() 启动有序关闭,其中先前提交的任务将被执行,但不会接受任何新任务

练习

需求:创建两个线程任务,一个线程任务完成1-100的和,一个线程任务返回一个字符串

1
2
3
4
5
6
public class MyString implements Callable<String> {
@Override
public String call() throws Exception {
return Thread.currentThread().getName();
}
}
1
2
3
4
5
6
7
8
9
10
public class MySum implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum+=i;
}
return sum;
}
}
1
2
3
4
5
6
7
8
9
10
public class Test01 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建线程池对象
ExecutorService es = Executors.newFixedThreadPool(2);
Future<String> f1 = es.submit(new MyString());
Future<Integer> f2 = es.submit(new MySum());
System.out.println(f1.get());
System.out.println(f2.get());
}
}