Java基础语法笔记

## 1. Java概述

### 1.1 Java语言背景介绍(了解)

语言:人与人交流沟通的表达方式

计算机语言:人与计算机之间进行信息交流沟通的一种特殊语言

Java语言是美国Sun公司(Stanford University Network)在1995年推出的计算机语言

Java之父:詹姆斯·高斯林(James Gosling)

2009年,Sun公司被甲骨文公司收购,所以我们现在访问oracle官网即可:[https://www.oracle.com](https://www.oracle.com/)

java语言的三个版本:

​ JavaSE: Java 语言的(标准版),用于桌面应用的开发,是其他两个版本的基础

​ JavaME: Java 语言的(小型版),用于嵌入式消费类电子设备

​ JavaEE: Java 语言的(企业版),用于 Web 方向的网站开发

### 1.2 Java语言跨平台原理(理解)

Java程序并非是直接运行的,Java编译器将Java源程序编译成与平台无关的字节码文件(class文件),然后由Java虚拟机(JVM)对字节码文件解释执行。所以在不同的操作系统下,只需安装不同的Java虚拟机即可实现java程序的跨平台。

### 1.3 JRE和JDK(记忆)

JVM(Java Virtual Machine),Java虚拟机

JRE(Java Runtime Environment),Java运行环境,包含了JVM和Java的核心类库(Java API)

JDK(Java Development Kit)称为Java开发工具,包含了JRE和开发工具

总结:我们只需安装JDK即可,它包含了java的运行环境和虚拟机。

### 1.4 JDK的下载和安装(应用)

#### 1.4.1 下载

通过官方网站获取JDK

[http://www.oracle.com](http://www.oracle.com/)

**注意**:针对不同的操作系统,需要下载对应版本的JDK。

#### 1.4.2 安装

傻瓜式安装,下一步即可。但默认的安装路径是在C:\Program Files下,为方便统一管理建议修改安装路径,将与开发相关的软件都安装到一个目录下,例如:E:\develop。

**注意**:安装路径不要包含中文或者空格等特殊字符(使用纯英文目录)。

#### 1.4.3 JDK的安装目录介绍

| 目录名称 | 说明 |
| -------- | ------------------------------------------------------------ |
| bin | 该路径下存放了JDK的各种工具命令。javac和java就放在这个目录。 |
| conf | 该路径下存放了JDK的相关配置文件。 |
| include | 该路径下存放了一些平台特定的头文件。 |
| jmods | 该路径下存放了JDK的各种模块。 |
| legal | 该路径下存放了JDK各模块的授权文档。 |
| lib | 该路径下存放了JDK工具的一些补充JAR包。 |

 

## 2. 第一个演示程序

### 2.1 常用DOS命令(应用)

在接触集成开发环境之前,我们需要使用命令行窗口对java程序进行编译和运行,所以需要知道一些常用DOS命令。

1、打开命令行窗口的方式:win + r打开运行窗口,输入cmd,回车。

2、常用命令及其作用

| 操作 | 说明 |
| ------------------ | --------------------------------- |
| 盘符名称: | 盘符切换。E:回车,表示切换到E盘。 |
| dir | 查看当前路径下的内容。 |
| cd 目录 | 进入单级目录。cd itheima |
| cd .. | 回退到上一级目录。 |
| cd 目录1\目录2\... | 进入多级目录。cd itheima\JavaSE |
| cd \ | 回退到盘符目录。 |
| cls | 清屏。 |
| exit | 退出命令提示符窗口。 |

### 2.2 Path环境变量的配置(应用)

#### 2.2.1 为什么配置环境变量

开发Java程序,需要使用JDK提供的开发工具(比如javac.exe、java.exe等命令),而这些工具在JDK的安装目录的bin目录下,如果不配置环境变量,那么这些命令只可以在该目录下执行。我们不可能把所有的java文件都放到JDK的bin目录下,所以配置环境变量的作用就是可以使bin目录下的java相关命令可以在任意目录下使用。

### 2.3 HelloWorld案例(应用)

HelloWorld案例是指在计算机屏幕上输出“HelloWorld”这行文字。

各种计算机语言都习惯使用该案例作为第一个演示案例。

#### 2.3.1 Java程序开发运行流程

开发Java程序,需要三个步骤:编写程序,编译程序,运行程序。

#### 2.3.2 HelloWorld案例的编写

1、新建文本文档文件,修改名称为HelloWorld.java。

2、用记事本打开HelloWorld.java文件,输写程序内容。

~~~java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
~~~

#### 2.3.3 HelloWorld案例的编译和运行

存文件,打开命令行窗口,将目录切换至java文件所在目录,编译java文件生成class文件,运行class文件。

> 编译:javac 文件名.java
>
> 范例:javac HelloWorld.java
>
> 执行:java 类名
>
> 范例:java HelloWorld

### 2.4 HelloWorld案例详解(理解)

![](img\图片1.jpg)

### 2.5 HelloWorld案例常见问题(理解)

#### 2.5.1 BUG

在电脑系统或程序中,隐藏着的一些未被发现的缺陷或问题统称为bug(漏洞)。

#### 2.5.2 BUG的解决

1、具备识别BUG的能力:多看

2、具备分析BUG的能力:多思考,多查资料

3、具备解决BUG的能力:多尝试,多总结

#### 2.5.3 HelloWorld案例常见问题

1、非法字符问题。Java中的符号都是英文格式的。

2、大小写问题。Java语言对大小写敏感(区分大小写)。

3、在系统中显示文件的扩展名,避免出现HelloWorld.java.txt文件。

4、编译命令后的java文件名需要带文件后缀.java

5、运行命令后的class文件名(类名)不带文件后缀

### 2.6 Notepad++软件的安装和使用(应用)

#### 2.6.1 什么要使用Notepad++软件

Notepad++功能比windows中的自带记事本功能强大,除了可以用来制作一般的纯文字说明文件,也十分适合编写计算机程序代码。Notepad++有行号,能够快速定位问题位置,还有语法高亮度显示、代码折叠等功能。而且它是免费的。

#### 2.6.2 Notepad++软件安装

安装:傻瓜式安装,一直下一步即可。建议也安装到统一的开发软件目录下,比如E:\develop。

#### 2.6.3Notepad++软件配置

安装完毕之后,为了使用方便,做一个简单的配置:修改默认语言和编码。

## 3. java基础语法

### 3.1 注释(理解)

注释是对代码的解释和说明文字,可以提高程序的可读性,因此在程序中添加必要的注释文字十分重要。Java中的注释分为三种:

单行注释。单行注释的格式是使用//,从//开始至本行结尾的文字将作为注释文字。

~~~java
// 这是单行注释文字
~~~

多行注释。多行注释的格式是使用/* 和 */将一段较长的注释括起来。

~~~java
/*
这是多行注释文字
这是多行注释文字
这是多行注释文字
*/
注意:多行注释不能嵌套使用。
~~~

文档注释。文档注释以`/**`开始,以`*/`结束。(以后讲)

### 3.2 关键字(理解)

关键字是指被java语言赋予了特殊含义的单词。

关键字的特点:

​ 关键字的字母全部小写。

​ 常用的代码编辑器对关键字都有高亮显示,比如现在我们能看到的public、class、static等。

### 3.3 常量(应用)

常量:在程序运行过程中,其值不可以发生改变的量。

Java中的常量分类:

​ 字符串常量 用双引号括起来的多个字符(可以包含0个、一个或多个),例如"a"、"abc"、"中国"等

​ 整数常量 整数,例如:-10、0、88等

​ 小数常量 小数,例如:-5.5、1.0、88.88等

​ 字符常量 用单引号括起来的一个字符,例如:'a'、'5'、'B'、'中'等

​ 布尔常量 布尔值,表示真假,只有两个值true和false

​ 空常量 一个特殊的值,空值,值为null

除空常量外,其他常量均可使用输出语句直接输出。

~~~java
public class Demo {
public static void main(String[] args) {
System.out.println(10); // 输出一个整数
System.out.println(5.5); // 输出一个小数
System.out.println('a'); // 输出一个字符
System.out.println(true); // 输出boolean值true
System.out.println("欢迎来到黑马程序员"); // 输出字符串
}
}
~~~

### 3.4 变量的介绍(理解)

变量的定义格式:

​ 数据类型 变量名 = 数据值;

​ 数据类型:为空间中存储的数据加入类型限制。整数?小数?

​ 变量名:自己要为空间起的名字,没有难度

​ 数据值: 空间中要存储的数值,没有难度

### 3.5 数据类型(应用)

#### 3.5.1 计算机存储单元

我们知道计算机是可以用来存储数据的,但是无论是内存还是硬盘,计算机存储设备的最小信息单元叫“位(bit)”,我们又称之为“比特位”,通常用小写的字母”b”表示。而计算机中最基本的存储单元叫“字节(byte)”,

通常用大写字母”B”表示,字节是由连续的8个位组成。

除了字节外还有一些常用的存储单位,其换算单位如下:

1B(字节) = 8bit

1KB = 1024B

1MB = 1024KB

1GB = 1024MB

1TB = 1024GB

#### 3.5.2 Java中的数据类型

Java是一个强类型语言,Java中的数据必须明确数据类型。在Java中的数据类型包括基本数据类型和引用数据类型两种。

Java中的基本数据类型:

| 数据类型 | 关键字 | 内存占用 | 取值范围 |
| :------- | ------------ | -------- | :----------------------------------------------------------- |
| 整数类型 | byte | 1 | -128~127 |
| | short | 2 | -32768~32767 |
| | int(默认) | 4 | -2的31次方到2的31次方-1 |
| | long | 8 | -2的63次方到2的63次方-1 |
| 浮点类型 | float | 4 | 负数:-3.402823E+38到-1.401298E-45 正数: 1.401298E-45到3.402823E+38 |
| | double(默认) | 8 | 负数:-1.797693E+308到-4.9000000E-324 正数:4.9000000E-324 到1.797693E+308 |
| 字符类型 | char | 2 | 0-65535 |
| 布尔类型 | boolean | 1 | true,false |

说明:

​ e+38表示是乘以10的38次方,同样,e-45表示乘以10的负45次方。

​ 在java中整数默认是int类型,浮点数默认是double类型。

### 3.6 变量(应用)

#### 3.6.1 变量的定义

变量:在程序运行过程中,其值可以发生改变的量。

从本质上讲,变量是内存中的一小块区域,其值可以在一定范围内变化。

变量的定义格式:

```java
数据类型 变量名 = 初始化值; // 声明变量并赋值
int age = 18;
System.out.println(age);
```

或者(扩展)

```java
// 先声明,后赋值(使用前赋值即可)
数据类型 变量名;
变量名 = 初始化值;
double money;
money = 55.5;
System.out.println(money);
```

还可以(扩展)

在同一行定义多个同一种数据类型的变量,中间使用逗号隔开。但不建议使用这种方式,降低程序的可读性。

```java
int a = 10, b = 20; // 定义int类型的变量a和b,中间使用逗号隔开
System.out.println(a);
System.out.println(b);

int c,d; // 声明int类型的变量c和d,中间使用逗号隔开
c = 30;
d = 40;
System.out.println(c);
System.out.println(d);
```

#### 3.6.2 变量的修改

```java
int a = 10;
a = 30; //修改变量的值
System.out.println(a);
```

变量前面不加数据类型时,表示修改已存在的变量的值。

### 3.7 变量的注意事项(理解)

1. 在同一对花括号中,变量名不能重复。
2. 变量在使用之前,必须初始化(赋值)。
3. 定义long类型的变量时,需要在整数的后面加L(大小写均可,建议大写)。因为整数默认是int类型,整数太大可能超出int范围。
4. 定义float类型的变量时,需要在小数的后面加F(大小写均可,建议大写)。因为浮点数的默认类型是double, double的取值范围是大于float的,类型不兼容。

### 3.8 键盘录入(理解)

我们可以通过 Scanner 类来获取用户的输入。使用步骤如下:

1、导包。Scanner 类在java.util包下,所以需要将该类导入。导包的语句需要定义在类的上面。

```java
import java.util.Scanner;
```

2、创建Scanner对象。

```java
Scanner sc = new Scanner(System.in);// 创建Scanner对象,sc表示变量名,其他均不可变
```

3、接收数据

```java
int i = sc.nextInt(); // 表示将键盘录入的值作为int数返回。
```

示例:

```java
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
//创建对象
Scanner sc = new Scanner(System.in);
//接收数据
int a = sc.nextInt();
//输出数据
System.out.println(a);
}
}
```

### 3.9 标识符(理解)

标识符是用户编程时使用的名字,用于给类、方法、变量、常量等命名。

Java中标识符的组成规则:

​ 由字母、数字、下划线“_”、美元符号“$”组成,第一个字符不能是数字。

​ 不能使用java中的关键字作为标识符。

​ 标识符对大小写敏感(区分大小写)。

Java中标识符的命名约定:

​ 小驼峰式命名:变量名、方法名

​ 首字母小写,从第二个单词开始每个单词的首字母大写。

​ 大驼峰式命名:类名

​ 每个单词的首字母都大写。

​ 另外,标识符的命名最好可以做到见名知意

​ 例如:username、studentNumber等。

# day02 - Java基础语法

## 1 类型转换

在Java中,一些数据类型之间是可以相互转换的。分为两种情况:自动类型转换和强制类型转换。

### 1.1 隐式转换(理解)

​ 把一个表示数据范围小的数值或者变量赋值给另一个表示数据范围大的变量。这种转换方式是自动的,直接书写即可。例如:

```java
double num = 10; // 将int类型的10直接赋值给double类型
System.out.println(num); // 输出10.0
```

​ 类型从小到大关系图:

​ ![](img\图片1.png)

说明:

1. 整数默认是int类型,byte、short和char类型数据参与运算均会自动转换为int类型。

```java
byte b1 = 10;
byte b2 = 20;
byte b3 = b1 + b2;
// 第三行代码会报错,b1和b2会自动转换为int类型,计算结果为int,int赋值给byte需要强制类型转换。
// 修改为:
int num = b1 + b2;
// 或者:
byte b3 = (byte) (b1 + b2);
```

2. boolean类型不能与其他基本数据类型相互转换。

### 1.2 强制转换(理解)

​ 把一个表示数据范围大的数值或者变量赋值给另一个表示数据范围小的变量。

​ 强制类型转换格式:目标数据类型 变量名 = (目标数据类型)值或者变量;

​ 例如:

```java
double num1 = 5.5;
int num2 = (int) num1; // 将double类型的num1强制转换为int类型
System.out.println(num2); // 输出5(小数位直接舍弃)
```

### 1.3 类型转换案例(理解)

案例代码:

```java
byte a = 3;
byte b = 4;
byte c = a + b; //错误。因为两个byte变量相加,会先提升为int类型
byte d = 3 + 4; //正确。常量优化机制
```

常量优化机制:

​ 在编译时,整数常量的计算会直接算出结果,并且会自动判断该结果是否在byte取值范围内,

​ 在:编译通过

不在:编译失败

## 2. 运算符

### 2.1 算术运算符

#### 2.1.1 运算符和表达式(了解)

运算符:对常量或者变量进行操作的符号

表达式:用运算符把常量或者变量连接起来符合java语法的式子就可以称为表达式。

​ 不同运算符连接的表达式体现的是不同类型的表达式。

举例说明:

```java
int a = 10;
int b = 20;
int c = a + b;
```

+:是运算符,并且是算术运算符。

a + b:是表达式,由于+是算术运算符,所以这个表达式叫算术表达式。

#### 2.1.2 算术运算符(应用)

| 符号 | 作用 | 说明 |
| ---- | ---- | ---------------------------- |
| + | 加 | 参看小学一年级 |
| - | 减 | 参看小学一年级 |
| * | 乘 | 参看小学二年级,与“×”相同 |
| / | 除 | 参看小学二年级,与“÷”相同 |
| % | 取余 | 获取的是两个数据做除法的余数 |

注意:

1. /和%的区别:两个数据做除法,/取结果的商,%取结果的余数。

2. 整数操作只能得到整数,要想得到小数,必须有浮点数参与运算。

~~~java
int a = 10;
int b = 3;
System.out.println(a / b); // 输出结果3
System.out.println(a % b); // 输出结果1
~~~

#### 2.1.3 字符的“+”操作(理解)

char类型参与算术运算,使用的是计算机底层对应的十进制数值。需要我们记住三个字符对应的数值:

'a' -- 97 a-z是连续的,所以'b'对应的数值是98,'c'是99,依次递加

'A' -- 65 A-Z是连续的,所以'B'对应的数值是66,'C'是67,依次递加

'0' -- 48 0-9是连续的,所以'1'对应的数值是49,'2'是50,依次递加

~~~java
// 可以通过使用字符与整数做算术运算,得出字符对应的数值是多少
char ch1 = 'a';
System.out.println(ch1 + 1); // 输出98,97 + 1 = 98

char ch2 = 'A';
System.out.println(ch2 + 1); // 输出66,65 + 1 = 66

char ch3 = '0';
System.out.println(ch3 + 1); // 输出49,48 + 1 = 49
~~~

算术表达式中包含不同的基本数据类型的值的时候,整个算术表达式的类型会自动进行提升。

提升规则:

byte类型,short类型和char类型将被提升到int类型,不管是否有其他类型参与运算。

整个表达式的类型自动提升到与表达式中最高等级的操作数相同的类型

​ 等级顺序:byte,short,char --> int --> long --> float --> double

例如:

~~~java
byte b1 = 10;
byte b2 = 20;
// byte b3 = b1 + b2; // 该行报错,因为byte类型参与算术运算会自动提示为int,int赋值给byte可能损失精度
int i3 = b1 + b2; // 应该使用int接收
byte b3 = (byte) (b1 + b2); // 或者将结果强制转换为byte类型
-------------------------------
int num1 = 10;
double num2 = 20.0;
double num3 = num1 + num2; // 使用double接收,因为num1会自动提升为double类型
~~~

#### 2.1.4 字符串的“+”操作(理解)

当“+”操作中出现字符串时,这个”+”是字符串连接符,而不是算术运算。

~~~java
System.out.println("itheima"+ 666); // 输出:itheima666
~~~

在”+”操作中,如果出现了字符串,就是连接运算符,否则就是算术运算。当连续进行“+”操作时,从左到右逐个执行。

~~~java
System.out.println(1 + 99 + "年黑马"); // 输出:100年黑马
System.out.println(1 + 2 + "itheima" + 3 + 4); // 输出:3itheima34
// 可以使用小括号改变运算的优先级
System.out.println(1 + 2 + "itheima" + (3 + 4)); // 输出:3itheima7
~~~

#### 2.1.5 数值拆分(应用)

需求:

​ 键盘录入一个三位数,将其拆分为个位,十位,百位,打印在控制台

示例代码:

```java
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
// 1:使用Scanner键盘录入一个三位数
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个三位数");
int num = sc.nextInt();
// 2:个位的计算:数值 % 10
int ge = num % 10;
// 3:十位的计算:数值 / 10 % 10
int shi = num / 10 % 10;
// 4:百位的计算:数值 / 100
int bai = num / 100;
// 5:将个位, 十位, 百位拼接上正确的字符串, 打印即可
System.out.println("整数"+num+"个位为:" + ge);
System.out.println("整数"+num+"十位为:" + shi);
System.out.println("整数"+num+"百位为:" + bai);

}
}
```

### 2.2 自增自减运算符(理解)

| 符号 | 作用 | 说明 |
| ---- | ---- | ----------- |
| ++ | 自增 | 变量的值加1 |
| -- | 自减 | 变量的值减1 |

注意事项:

​ ++和-- 既可以放在变量的后边,也可以放在变量的前边。

​ 单独使用的时候, ++和-- 无论是放在变量的前边还是后边,结果是一样的。

​ 参与操作的时候,如果放在变量的后边,先拿变量参与操作,后拿变量做++或者--。

​ 参与操作的时候,如果放在变量的前边,先拿变量做++或者--,后拿变量参与操作。

​ 最常见的用法:单独使用。

```java
int i = 10;
i++; // 单独使用
System.out.println("i:" + i); // i:11

int j = 10;
++j; // 单独使用
System.out.println("j:" + j); // j:11

int x = 10;
int y = x++; // 赋值运算,++在后边,所以是使用x原来的值赋值给y,x本身自增1
System.out.println("x:" + x + ", y:" + y); // x:11,y:10

int m = 10;
int n = ++m; // 赋值运算,++在前边,所以是使用m自增后的值赋值给n,m本身自增1
System.out.println("m:" + m + ", m:" + m); // m:11,m:11
```

练习:

```java
int x = 10;
int y = x++ + x++ + x++;
System.out.println(y); // y的值是多少?
/*
解析,三个表达式都是++在后,所以每次使用的都是自增前的值,但程序自左至右执行,所以第一次自增时,使用的是10进行计算,但第二次自增时,x的值已经自增到11了,所以第二次使用的是11,然后再次自增。。。
所以整个式子应该是:int y = 10 + 11 + 12;
输出结果为33。
*/
注意:通过此练习深刻理解自增和自减的规律,但实际开发中强烈建议不要写这样的代码!小心挨打!
```

### 2.3 赋值运算符(应用)

赋值运算符的作用是将一个表达式的值赋给左边,左边必须是可修改的,不能是常量。

| 符号 | 作用 | 说明 |
| ---- | ---------- | --------------------- |
| = | 赋值 | a=10,将10赋值给变量a |
| += | 加后赋值 | a+=b,将a+b的值给a |
| -= | 减后赋值 | a-=b,将a-b的值给a |
| *= | 乘后赋值 | a*=b,将a×b的值给a |
| /= | 除后赋值 | a/=b,将a÷b的商给a |
| %= | 取余后赋值 | a%=b,将a÷b的余数给a |

注意:

扩展的赋值运算符隐含了强制类型转换。

~~~java
short s = 10;
s = s + 10; // 此行代码报出,因为运算中s提升为int类型,运算结果int赋值给short可能损失精度

s += 10; // 此行代码没有问题,隐含了强制类型转换,相当于 s = (short) (s + 10);
~~~

### 2.4 关系运算符(应用)

关系运算符有6种关系,分别为小于、小于等于、大于、等于、大于等于、不等于。

| 符号 | 说明 |
| ---- | ------------------------------------------------------- |
| == | a==b,判断a和b的值是否相等,成立为true,不成立为false |
| != | a!=b,判断a和b的值是否不相等,成立为true,不成立为false |
| > | a>b,判断a是否大于b,成立为true,不成立为false |
| >= | a>=b,判断a是否大于等于b,成立为true,不成立为false |
| < | a<b,判断a是否小于b,成立为true,不成立为false |
| <= | a<=b,判断a是否小于等于b,成立为true,不成立为false |

注意事项:

​ 关系运算符的结果都是boolean类型,要么是true,要么是false。

​ 千万不要把“==”误写成“=”,"=="是判断是否相等的关系,"="是赋值。

~~~java
int a = 10;
int b = 20;
System.out.println(a == b); // false
System.out.println(a != b); // true
System.out.println(a > b); // false
System.out.println(a >= b); // false
System.out.println(a < b); // true
System.out.println(a <= b); // true

// 关系运算的结果肯定是boolean类型,所以也可以将运算结果赋值给boolean类型的变量
boolean flag = a > b;
System.out.println(flag); // 输出false
~~~

### 2.5 逻辑运算符(应用)

逻辑运算符把各个运算的关系表达式连接起来组成一个复杂的逻辑表达式,以判断程序中的表达式是否成立,判断的结果是 true 或 false。

| 符号 | 作用 | 说明 |
| ---- | -------- | -------------------------------------------- |
| & | 逻辑与 | a&b,a和b都是true,结果为true,否则为false |
| \| | 逻辑或 | a\|b,a和b都是false,结果为false,否则为true |
| ^ | 逻辑异或 | a^b,a和b结果不同为true,相同为false |
| ! | 逻辑非 | !a,结果和a的结果正好相反 |

~~~java
//定义变量
int i = 10;
int j = 20;
int k = 30;

//& “与”,并且的关系,只要表达式中有一个值为false,结果即为false
System.out.println((i > j) & (i > k)); //false & false,输出false
System.out.println((i < j) & (i > k)); //true & false,输出false
System.out.println((i > j) & (i < k)); //false & true,输出false
System.out.println((i < j) & (i < k)); //true & true,输出true
System.out.println("--------");

//| “或”,或者的关系,只要表达式中有一个值为true,结果即为true
System.out.println((i > j) | (i > k)); //false | false,输出false
System.out.println((i < j) | (i > k)); //true | false,输出true
System.out.println((i > j) | (i < k)); //false | true,输出true
System.out.println((i < j) | (i < k)); //true | true,输出true
System.out.println("--------");

//^ “异或”,相同为false,不同为true
System.out.println((i > j) ^ (i > k)); //false ^ false,输出false
System.out.println((i < j) ^ (i > k)); //true ^ false,输出true
System.out.println((i > j) ^ (i < k)); //false ^ true,输出true
System.out.println((i < j) ^ (i < k)); //true ^ true,输出false
System.out.println("--------");

//! “非”,取反
System.out.println((i > j)); //false
System.out.println(!(i > j)); //!false,,输出true
~~~

### 2.6 短路逻辑运算符(理解)

| 符号 | 作用 | 说明 |
| ---- | ------ | ---------------------------- |
| && | 短路与 | 作用和&相同,但是有短路效果 |
| \|\| | 短路或 | 作用和\|相同,但是有短路效果 |

在逻辑与运算中,只要有一个表达式的值为false,那么结果就可以判定为false了,没有必要将所有表达式的值都计算出来,短路与操作就有这样的效果,可以提高效率。同理在逻辑或运算中,一旦发现值为true,右边的表达式将不再参与运算。

- 逻辑与&,无论左边真假,右边都要执行。

- 短路与&&,如果左边为真,右边执行;如果左边为假,右边不执行。

- 逻辑或|,无论左边真假,右边都要执行。

- 短路或||,如果左边为假,右边执行;如果左边为真,右边不执行。

~~~java
int x = 3;
int y = 4;
System.out.println((x++ > 4) & (y++ > 5)); // 两个表达都会运算
System.out.println(x); // 4
System.out.println(y); // 5

System.out.println((x++ > 4) && (y++ > 5)); // 左边已经可以确定结果为false,右边不参与运算
System.out.println(x); // 4
System.out.println(y); // 4
~~~

### 2.7 三元运算符(理解)

三元运算符语法格式:

~~~java
关系表达式 ? 表达式1 : 表达式2;
~~~

解释:问号前面的位置是判断的条件,判断结果为boolean型,为true时调用表达式1,为false时调用表达式2。其逻辑为:如果条件表达式成立或者满足则执行表达式1,否则执行第二个。

举例:

~~~java
int a = 10;
int b = 20;
int c = a > b ? a : b; // 判断 a>b 是否为真,如果为真取a的值,如果为假,取b的值
~~~

### 2.8 三元运算符案例(应用)

需求:

​ 一座寺庙里住着三个和尚,已知他们的身高分别为150cm、210cm、165cm,请用程序实现获取这三个和尚的最高身高。

~~~java
public class OperatorTest02 {
public static void main(String[] args) {
//1:定义三个变量用于保存和尚的身高,单位为cm,这里仅仅体现数值即可。
int height1 = 150;
int height2 = 210;
int height3 = 165;
//2:用三元运算符获取前两个和尚的较高身高值,并用临时身高变量保存起来。
int tempHeight = height1 > height2 ? height1 : height2;
//3:用三元运算符获取临时身高值和第三个和尚身高较高值,并用最大身高变量保存。
int maxHeight = tempHeight > height3 ? tempHeight : height3;
//4:输出结果
System.out.println("maxHeight:" + maxHeight);
}
}
~~~

## 3. 流程控制语句

在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的。所以,我们必须清楚每条语句的执行流程。而且,很多时候要通过控制语句的执行顺序来实现我们想要的功能。

### 3.1 流程控制语句分类(了解)

​ 顺序结构

​ 分支结构(if, switch)

​ 循环结构(for, while, do…while)

### 3.2 顺序结构(了解)

顺序结构是程序中最简单最基本的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。

顺序结构执行流程图:

![1545615769372](img/图片2.png)

### 3.3 分支结构之if语句

#### 3.3.1 if语句格式1(理解)

~~~java
格式:
if (关系表达式) {
语句体;
}
~~~

执行流程:

①首先计算关系表达式的值

②如果关系表达式的值为true就执行语句体

③如果关系表达式的值为false就不执行语句体

④继续执行后面的语句内容

![1545616039363](img/图片3.png)

示例:

~~~java
public class IfDemo {
public static void main(String[] args) {
System.out.println("开始");

// 如果年龄大于18岁, 就可以上网吧
int age = 17;

if(age >= 18){
// int a = 10;
System.out.println("可以上网吧");
}

System.out.println("结束");
}
}
~~~

#### 3.3.2 if语句格式2(理解)

~~~java
格式:
if (关系表达式) {
语句体1;
} else {
语句体2;
}
~~~

执行流程:

①首先计算关系表达式的值

②如果关系表达式的值为true就执行语句体1

③如果关系表达式的值为false就执行语句体2

④继续执行后面的语句内容

![1545616221283](img/图片4.png)

示例:奇偶数

​ 任意给出一个整数,请用程序实现判断该整数是奇数还是偶数,并在控制台输出该整数是奇数还是偶数。

~~~java
public class Demo2If {
public static void main(String[] args) {
// 程序判断一个数, 是奇数还是偶数
int num = 9;

if(num % 2 == 0){
System.out.println("偶数");
}else{
System.out.println("奇数");
}
}
}
~~~

#### 3.3.3 if语句格式3(理解)

~~~java
格式:
if (关系表达式1) {
语句体1;
} else if (关系表达式2) {
语句体2;
}

else {
语句体n+1;
}
~~~

执行流程:

①首先计算关系表达式1的值

②如果值为true就执行语句体1;如果值为false就计算关系表达式2的值

③如果值为true就执行语句体2;如果值为false就计算关系表达式3的值

④…

⑤如果没有任何关系表达式为true,就执行语句体n+1。

![1545616667104](img\图片5.png)

示例:

​ 定义一个在0~100之间的变量a, 90~100优秀,80~89良好,70~79中等,60~69及格,0~59请努力加油!

~~~java
public class Demo3If {
public static void main(String[] args){
int score = 65;
if(score >= 90 && score <= 100){
System.out.println("优秀");
}else if (score >= 80 && score <= 89){
System.out.println("良好");
}else if (score >= 70 && score <= 79){
System.out.println("中等");
}else if (score >= 60 && score <= 69){
System.out.println("及格");
}else if (score >= 0 && score <= 59){
System.out.println("请努力加油");
}else{
System.out.println("成绩有误!");
}
}
}
~~~

#### 3.3.4 if语句格式3案例(应用)

需求:小明快要期末考试了,小明爸爸对他说,会根据他不同的考试成绩,送他不同的礼物,假如你可以控制小明的得分,请用程序实现小明到底该获得什么样的礼物,并在控制台输出。

分析:

​ ①小明的考试成绩未知,可以使用键盘录入的方式获取值

​ ②由于奖励种类较多,属于多种判断,采用if...else...if格式实现

​ ③为每种判断设置对应的条件

​ ④为每种判断设置对应的奖励

~~~java
import java.util.Scanner;
public class IfTest02 {
public static void main(String[] args){
// 1. 使用Scanner录入考试成绩
Scanner sc = new Scanner(System.in);
System.out.println("请输入您的成绩:");
int score = sc.nextInt();
// 2. 判断成绩是否在合法范围内 0~100
if(score >=0 && score <= 100){
// 合法成绩
// 3. 在合法的语句块中判断成绩范围符合哪一个奖励
if(score >= 95 && score <= 100){
System.out.println("自行车一辆");
}else if(score >= 90 && score <= 94){
System.out.println("游乐场一次");
}else if(score >= 80 && score <= 89){
System.out.println("变形金刚一个");
}else {
System.out.println("挨顿揍, 这座城市又多了一个伤心的人~");
}
}else{
// 非法的话, 给出错误提示
System.out.println("您的成绩输入有误!");
}
}
}
~~~

## 1. switch语句

### 1.1 分支语句switch语句

* 格式

```java
switch (表达式) {
case 1:
语句体1;
break;
case 2:
语句体2;
break;
...
default:
语句体n+1;
break;
}
```

* 执行流程:

* 首先计算出表达式的值
* 其次,和case依次比较,一旦有对应的值,就会执行相应的语句,在执行的过程中,遇到break就会结 束。
* 最后,如果所有的case都和表达式的值不匹配,就会执行default语句体部分,然后程序结束掉。

### 1.2 switch案例-减肥计划

* 需求:键盘录入星期数,显示今天的减肥活动

```
周一:跑步
周二:游泳
周三:慢走
周四:动感单车
周五:拳击
周六:爬山
周日:好好吃一顿
```

* 示例代码:

```java
public static void main(String[] args){
// 1. 键盘录入星期数据,使用变量接收
Scanner sc = new Scanner(System.in);
System.out.println("请输入");
int week = sc.nextInt();
// 2. 多情况判断,采用switch语句实现
switch(week){
// 3. 在不同的case中,输出对应的减肥计划
case 1:
System.out.println("跑步");
break;
case 2:
System.out.println("游泳");
break;
case 3:
System.out.println("慢走");
break;
case 4:
System.out.println("动感单车");
break;
case 5:
System.out.println("拳击");
break;
case 6:
System.out.println("爬山");
break;
case 7:
System.out.println("好好吃一顿");
break;
default:
System.out.println("您的输入有误");
break;
}
}
}
```

### 1.3 switch语句case穿透

- 概述 : 如果switch语句中,case省略了break语句, 就会开始case穿透
- 需求 : 键盘录入星期数,输出工作日、休息日 (1-5)工作日,(6-7)休息日
- 示例代码:

```java
/*
case穿透是如何产生的?

如果switch语句中,case省略了break语句, 就会开始case穿透.

现象:
当开始case穿透,后续的case就不会具有匹配效果,内部的语句都会执行
直到看见break,或者将整体switch语句执行完毕,才会结束。
*/
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入星期数:");
int week = sc.nextInt();

switch(week){
case 1:
case 2:
case 3:
case 4:
case 5:
System.out.println("工作日");
break;
case 6:
case 7:
System.out.println("休息日");
break;
default:
System.out.println("您的输入有误");
break;
}
}
}
```
## 2. for循环

### 2.1 循环语句-for循环

* 循环:

循环语句可以在满足循环条件的情况下,反复执行某一段代码,这段被重复执行的代码被称为循环体语句,当反复 执行这个循环体时,需要在合适的时候把循环判断条件修改为false,从而结束循环,否则循环将一直执行下去,形 成死循环。

* for循环格式:

```java
for (初始化语句;条件判断语句;条件控制语句) {
循环体语句;
}
```

* 格式解释:

* 初始化语句: 用于表示循环开启时的起始状态,简单说就是循环开始的时候什么样
* 条件判断语句:用于表示循环反复执行的条件,简单说就是判断循环是否能一直执行下去
* 循环体语句: 用于表示循环反复执行的内容,简单说就是循环反复执行的事情
* 条件控制语句:用于表示循环执行中每次变化的内容,简单说就是控制循环是否能执行下去

* 执行流程:

①执行初始化语句

②执行条件判断语句,看其结果是true还是false

​ 如果是false,循环结束

​ 如果是true,继续执行

③执行循环体语句

④执行条件控制语句

⑤回到②继续

### 2.2 for循环案例-输出数据1-5和5-1

* 需求:在控制台输出1-5和5-1的数据
* 示例代码:

```java
public class ForTest01 {
public static void main(String[] args) {
//需求:输出数据1-5
for(int i=1; i<=5; i++) {
System.out.println(i);
}
System.out.println("--------");
//需求:输出数据5-1
for(int i=5; i>=1; i--) {
System.out.println(i);
}
}
}
```

### 2.3 for循环案例-求1-5数据和

* 需求:求1-5之间的数据和,并把求和结果在控制台输出
* 示例代码:

```java
public class ForTest02 {
public static void main(String[] args) {
//求和的最终结果必须保存起来,需要定义一个变量,用于保存求和的结果,初始值为0
int sum = 0;
//从1开始到5结束的数据,使用循环结构完成
for(int i=1; i<=5; i++) {
//将反复进行的事情写入循环结构内部
// 此处反复进行的事情是将数据 i 加到用于保存最终求和的变量 sum 中
sum += i;
/*
sum += i; sum = sum + i;
第一次:sum = sum + i = 0 + 1 = 1;
第二次:sum = sum + i = 1 + 2 = 3;
第三次:sum = sum + i = 3 + 3 = 6;
第四次:sum = sum + i = 6 + 4 = 10;
第五次:sum = sum + i = 10 + 5 = 15;
*/
}
//当循环执行完毕时,将最终数据打印出来
System.out.println("1-5之间的数据和是:" + sum);
}
}
```

* 本题要点:
* 今后遇到的需求中,如果带有求和二字,请立即联想到求和变量
* 求和变量的定义位置,必须在循环外部,如果在循环内部则计算出的数据将是错误的

### 2.4 for循环案例-求1-100偶数和

* 需求:求1-100之间的偶数和,并把求和结果在控制台输出 }
* 示例代码:

```java
public class ForTest03 {
public static void main(String[] args) {
//求和的最终结果必须保存起来,需要定义一个变量,用于保存求和的结果,初始值为0
int sum = 0;
//对1-100的数据求和与1-5的数据求和几乎完全一样,仅仅是结束条件不同
for(int i=1; i<=100; i++) {
//对1-100的偶数求和,需要对求和操作添加限制条件,判断是否是偶数
if(i%2 == 0) {
sum += i;
}
}
//当循环执行完毕时,将最终数据打印出来
System.out.println("1-100之间的偶数和是:" + sum);
}
}
```

### 2.5 for循环案例-水仙花数

* 需求:在控制台输出所有的“水仙花数”
* 解释:什么是水仙花数?
* 水仙花数,指的是一个三位数,个位、十位、百位的数字立方和等于原数
* 例如`153 3*3*3 + 5*5*5 + 1*1*1 = 153`
* 思路:
1. 获取所有的三位数,准备进行筛选,最小的三位数为100,最大的三位数为999,使用for循环获取
2. 获取每一个三位数的个位,十位,百位,做if语句判断是否是水仙花数
* 示例代码

```java
public class ForTest04 {
public static void main(String[] args) {
//输出所有的水仙花数必然要使用到循环,遍历所有的三位数,三位数从100开始,到999结束
for(int i=100; i<1000; i++) {
//在计算之前获取三位数中每个位上的值
int ge = i%10;
int shi = i/10%10;
int bai = i/10/10%10;

//判定条件是将三位数中的每个数值取出来,计算立方和后与原始数字比较是否相等
if(ge*ge*ge + shi*shi*shi + bai*bai*bai == i) {
//输出满足条件的数字就是水仙花数
System.out.println(i);
}
}
}
}
```

### 2.6 for循环案例-每行打印2个水仙花数(统计)

* 需求:在控制台输出所有的“水仙花数”,要求每行打印2个
* 示例代码:

```java
public class Demo6For {
/*
需求:在控制台输出所有的“水仙花数”,要求每行打印2个

System.out.print (打印内容); 打印后不换行
System.out.println(打印内容); 打印后换行

分析:

1. 定义变量count,用于保存“打印过”的数量,初始值为0
2. 在判定和打印水仙花数的过程中,拼接空格, 但不换行,并在打印后让count变量+1,记录打印过的数量
3. 在每一次count变量+1后,判断是否到达了2的倍数,是的话,换行。

*/
public static void main(String[] args){
// 1. 定义变量count,用于保存“打印过”的数量,初始值为0
int count = 0;
for(int i = 100; i <= 999; i++){
int ge = i % 10;
int shi = i / 10 % 10;
int bai = i / 10 / 10 % 10;

if( (ge*ge*ge + shi*shi*shi + bai*bai*bai) == i){
// 2. 在判定和打印水仙花数的过程中,拼接空格, 但不换行,并在打印后让count变量+1,记录打印过的数量
System.out.print(i + " ");
count++;
// 3. 在每一次count变量+1后,判断是否到达了2的倍数,是的话,换行
if(count % 2 == 0){
System.out.println();
}
}
}
}
}
```

* 本题要点:
* 今后如果需求带有统计xxx,请先想到计数器变量
* 计数器变量定义的位置,必须在循环外部

## 3. while循环

### 3.1 循环语句-while循环

* while循环完整格式:

```java
初始化语句;
while (条件判断语句) {
循环体语句;
条件控制语句;
}
```

* while循环执行流程:

①执行初始化语句

②执行条件判断语句,看其结果是true还是false

​ 如果是false,循环结束

​ 如果是true,继续执行

③执行循环体语句

④执行条件控制语句

⑤回到②继续

* 示例代码:

```java
public class WhileDemo {
public static void main(String[] args) {
//需求:在控制台输出5次"HelloWorld"
//for循环实现
for(int i=1; i<=5; i++) {
System.out.println("HelloWorld");
}
System.out.println("--------");
//while循环实现
int j = 1;
while(j<=5) {
System.out.println("HelloWorld");
j++;
}
}
}
```

### 3.2 while循环案例-珠穆朗玛峰

* 需求:世界最高山峰是珠穆朗玛峰(8844.43米=8844430毫米),假如我有一张足够大的纸,它的厚度是0.1毫米。请问,我折叠多少次,可以折成珠穆朗玛峰的高度?
* 示例代码:

```java
public class WhileTest {
public static void main(String[] args) {
//定义一个计数器,初始值为0
int count = 0;
//定义纸张厚度
double paper = 0.1;
//定义珠穆朗玛峰的高度
int zf = 8844430;
//因为要反复折叠,所以要使用循环,但是不知道折叠多少次,这种情况下更适合使用while循环
//折叠的过程中当纸张厚度大于珠峰就停止了,因此继续执行的要求是纸张厚度小于珠峰高度
while(paper <= zf) {
//循环的执行过程中每次纸张折叠,纸张的厚度要加倍
paper *= 2;
//在循环中执行累加,对应折叠了多少次
count++;
}
//打印计数器的值
System.out.println("需要折叠:" + count + "次");
}
}
```

## 4. 循环细节

### 4.1 循环语句-dowhile循环

* 完整格式:

```java
初始化语句;
do {
循环体语句;
条件控制语句;
}while(条件判断语句);
```

* 执行流程:

① 执行初始化语句

② 执行循环体语句

③ 执行条件控制语句

④ 执行条件判断语句,看其结果是true还是false

如果是false,循环结束

如果是true,继续执行

⑤ 回到②继续

* 示例代码:

```java
public class DoWhileDemo {
public static void main(String[] args) {
//需求:在控制台输出5次"HelloWorld"
//for循环实现
for(int i=1; i<=5; i++) {
System.out.println("HelloWorld");
}
System.out.println("--------");
//do...while循环实现
int j = 1;
do {
System.out.println("HelloWorld");
j++;
}while(j<=5);
}
}
```

### 4.2 三种循环的区别

* 三种循环的区别
* for循环和while循环先判断条件是否成立,然后决定是否执行循环体(先判断后执行)
* do...while循环先执行一次循环体,然后判断条件是否成立,是否继续执行循环体(先执行后判断)
* for循环和while的区别
* 条件控制语句所控制的自增变量,因为归属for循环的语法结构中,在for循环结束后,就不能再次被访问到了
* 条件控制语句所控制的自增变量,对于while循环来说不归属其语法结构中,在while循环结束后,该变量还可以继续使用
* 死循环(无限循环)的三种格式
1. for(;;){}
2. while(true){}
3. do {} while(true);

### 4.3 死循环

- 死循环格式

```
for死循环格式 :
for(;;){

}

while死循环格式 :

while(true){

}

do..while死循环格式 :

do{

}while(true);
```

- 死循环案例

```java
/*
问题: 死循环有应用场景吗?

例如: 键盘录入一个1-100之间的整数

顾虑: 键盘录入是用户操作的, 用户就可能会出现一些误操作的现象

*/
public static void main(String[] args) {
/*
for(;;){
System.out.println("我停不下来了~");
}
*/

/*
while(true){
System.out.println("我停不下来了~");
}
*/

do{
System.out.println("我停不下来了~");
}while(true);

System.out.println("看看我能被执行吗?~"); // 无法访问的语句
}
}
```

 

### 4.4 跳转控制语句

* 跳转控制语句(break)
* 跳出循环,结束循环
* 跳转控制语句(continue)
* 跳过本次循环,继续下次循环
* 注意: continue只能在循环中进行使用!

```java
public class Demo1Continue {
/*
continue : 跳过某次循环体内容的执行

注意:使用是基于条件控制, 在循环内部使用.

需求: 模拟电梯上行的过程 1-24层, 4层不停.
*/
public static void main(String[] args){
for(int i = 1; i <= 24; i++){
if(i == 4){
continue;
}
System.out.println(i + "层到了~");
}
}

}
```

```java
public class Demo2Break {
/*
break : 终止循环体内容的执行
注意:使用是基于条件控制的
break语句只能在循环和switch中进行使用.

需求: 模拟20岁工作到80岁, 60岁退休.
*/
public static void main(String[] args){
for(int i = 20; i <= 80; i++){
if(i == 60){
break; // 结束整个循环
}
System.out.println(i + "岁正在上班");
}
}

}
```

```java
import java.util.Scanner;

public class Test {
/*
需求:程序运行后,用户可多次查询星期对应的减肥计划,直到输入0,程序结束

步骤:

1. 不明确用户操作几次, 使用死循环包裹业务逻辑
2. 匹配到0的时候,使用break结束循环死循环

*/
public static void main (String[] args){

lo:while(true){
System.out.println("请输入您要查看的星期数:");
System.out.println("(如无需继续查看,请输入0退出程序)");

// 1. 键盘录入星期数据,使用变量接收
Scanner sc = new Scanner(System.in);
int week = sc.nextInt();
// 2. 多情况判断,采用switch语句实现
switch(week){
// 3. 在不同的case中,输出对应的减肥计划
case 0:
System.out.println("感谢您的使用");
break lo;
case 1:
System.out.println("跑步");
break;
case 2:
System.out.println("游泳");
break;
case 3:
System.out.println("慢走");
break;
case 4:
System.out.println("动感单车");
break;
case 5:
System.out.println("拳击");
break;
case 6:
System.out.println("爬山");
break;
case 7:
System.out.println("好好吃一顿");
break;
default:
System.out.println("您的输入有误");
break;
}
}

}
}
```

 

## 5. Random

### 5.1 Random产生随机数(掌握)

* 概述:

* Random类似Scanner,也是Java提供好的API,内部提供了产生随机数的功能
* API后续课程详细讲解,现在可以简单理解为Java已经写好的代码

* 使用步骤:

1. 导入包

import java.util.Random;

2. 创建对象

Random r = new Random();

3. 产生随机数

int num = r.nextInt(10);

解释: 10代表的是一个范围,如果括号写10,产生的随机数就是0-9,括号写20,参数的随机数则是0-19

* 示例代码:

```java
import java.util.Random;

public class Demo1Random {
/*
Random : 产生随机数

1. 导包 : import java.util.Random;
导包的动作必须出现在类定义的上面

2. 创建对象 : Random r = new Random();
上面这个格式里面,r 是变量名,可以变,其他的都不允许变

3. 获取随机数 : int number = r.nextInt(10); //获取数据的范围:[0,10) 包括0,不包括10
上面这个格式里面,number是变量名,可以变,数字10可以变。其他的都不允许变

需求: 产生随机数1-10之间的
*/
public static void main(String[] args){
// 2. 创建对象
Random r = new Random();

for(int i = 1; i <= 10; i++){
// 3. 获取随机数
int num = r.nextInt(10) + 1; // 1-10
System.out.println(num);
}

}
}
```

### 5.3 Random练习-猜数字(应用)

* 需求:

程序自动生成一个1-100之间的数字,使用程序实现猜出这个数字是多少?

当猜错的时候根据不同情况给出相应的提示

A. 如果猜的数字比真实数字大,提示你猜的数据大了

B. 如果猜的数字比真实数字小,提示你猜的数据小了

C. 如果猜的数字与真实数字相等,提示恭喜你猜中了

* 示例代码:

```java
import java.util.Scanner;
import java.util.Random;

public class Test {
/*
需求:程序自动生成一个1-100之间的数字,使用程序实现猜出这个数字是多少?
当猜错的时候根据不同情况给出相应的提示
如果猜的数字比真实数字大,提示你猜的数据大了
如果猜的数字比真实数字小,提示你猜的数据小了
如果猜的数字与真实数字相等,提示恭喜你猜中了

1. 准备Random和Scanner对象, 分别用于产生随机数和键盘录入
2. 使用Random产生一个1-100之间的数, 作为要猜的数
3. 键盘录入用户猜的的数据
4. 使用录入的数据(用户猜的数据)和随机数(要猜的数据)进行比较, 并给出提示

5. 以上内容需要多次进行, 但无法预估用户输入几次可以猜测正确, 使用while(true)死循环包裹
6. 猜对之后, break结束.

*/
public static void main(String[] args){
// 1. 准备Random和Scanner对象, 分别用于产生随机数和键盘录入
Random r = new Random();
Scanner sc = new Scanner(System.in);
// 2. 使用Random产生一个1-100之间的数, 作为要猜的数
int randomNum = r.nextInt(100) + 1;

// 5. 以上内容需要多次进行, 但无法预估用户输入几次可以猜测正确, 使用while(true)死循环包裹
while(true){
// 3. 键盘录入用户猜的的数据
System.out.println("请输入您猜的数据:");
int num = sc.nextInt();
// 4. 使用录入的数据(用户猜的数据)和随机数(要猜的数据)进行比较, 并给出提示
if(num > randomNum){
System.out.println("猜大了");
}else if(num < randomNum){
System.out.println("猜小了");
}else{
// 6. 猜对之后, break结束.
System.out.println("恭喜,猜中了");
break;
}
}

System.out.println("感谢您的使用");

}
}
```

## 第一部分 : IDEA开发工具

**参见 :IEDA的安装请参考文件夹PPT中的 04_IDEA.ppt**

## 1.数组

### 1.1 数组介绍

​ 数组就是存储数据长度固定的容器,存储多个数据的数据类型要一致。

### 1.2 数组的定义格式

#### 1.2.1 第一种格式

​ 数据类型[] 数组名

​ 示例:

```java
int[] arr;
double[] arr;
char[] arr;
```

#### 1.2.2 第二种格式

​ 数据类型 数组名[]

​ 示例:

```java
int arr[];
double arr[];
char arr[];
```

### 1.3 数组的动态初始化

#### 1.3.1 什么是动态初始化

​ 数组动态初始化就是只给定数组的长度,由系统给出默认初始化值

#### 1.3.2 动态初始化格式

```java
数据类型[] 数组名 = new 数据类型[数组长度];
```

```java
int[] arr = new int[3];
```

#### 1.3.3 动态初始化格式详解

- 等号左边:

- int:数组的数据类型

- []:代表这是一个数组

- arr:代表数组的名称

- 等号右边:

- new:为数组开辟内存空间
- int:数组的数据类型
- []:代表这是一个数组
- 5:代表数组的长度

**代码 :**

```java
package com.itheima.array;

public class Demo2Array {
/*
数组的动态初始化:
在初始化的时候, 需要手动指定数组的长度, 系统会为数组容器分配初始值.

动态初始化格式:
数据类型[] 数组名 = new 数据类型[数组的长度];

注意:
打印数组变量的时候, 会打印出数组的内存地址

[I@10f87f48 :

@ : 分隔符
[ : 当前的空间是一个数组类型
I : 当前数组容器中所存储的数据类型
10f87f48 : 十六进制内存地址

0 1 2 3 4 5 6 7 8 9 a b c d e f
*/
public static void main(String[] args) {
// 数据类型[] 数组名 = new 数据类型[数组的长度];
// 通过new关键字创建了一个int类型的数组容器, 该容器可以存储5个int类型的整数, 该容器被arr数组变量所记录
int[] arr = new int[5];
// [I@10f87f48
System.out.println(arr);

byte[] bArr = new byte[3];
// [B@b4c966a
System.out.println(bArr);

}
}

```

 

### 1.4 数组元素访问

#### 1.4.1 什么是索引

​ 每一个存储到数组的元素,都会自动的拥有一个编号,从0开始。

​ 这个自动编号称为数组索引(index),可以通过数组的索引访问到数组中的元素。

#### 1.4.2访问数组元素格式

```java
数组名[索引];
```

#### 1.4.3示例代码

```java
package com.itheima.array;

public class Demo3ArrayIndex {
/*
数组动态初始化:
初始化的时候, 手动指定数组长度, 系统会为数组容器分配初始值.

数组的元素访问格式:
数组名[索引]

索引: 数组中数据的编号方式, 编号从0开始
作用: 访问数组容器中的空间位置

注意:
数组在创建完毕后, 即使没有赋值, 也可以取出, 但取出的元素都是默认初始化值.

*/
public static void main(String[] args) {
int[] arr = new int[3]; // 0 1 2
System.out.println(arr); // 数组的内存地址 [I@10f87f48

// 数组名[索引] 访问数组容器中的空间位置
System.out.println(arr[0]); // 0 系统自动分配的默认初始化值
System.out.println(arr[1]);
System.out.println(arr[2]);

System.out.println("--------------");

// 数组名[索引]
arr[0] = 11;
arr[1] = 22;
arr[2] = 33;

System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
}
}
```

### 1.5 内存分配

#### 1.5.1 内存概述

​ 内存是计算机中的重要原件,临时存储区域,作用是运行程序。

​ 我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的。

​ 必须放进内存中才能运行,运行完毕后会清空内存。

​ Java虚拟机要运行程序,必须要对内存进行空间的分配和管理。

#### 1.5.2 java中的内存分配

- 目前我们只需要记住两个内存,分别是:栈内存和堆内存

| 区域名称 | 作用 |
| ---------- | ---------------------------------------------------------- |
| 寄存器 | 给CPU使用,和我们开发无关。 |
| 本地方法栈 | JVM在使用操作系统功能的时候使用,和我们开发无关。 |
| 方法区 | 存储可以运行的class文件。 |
| 堆内存 | 存储对象或者数组,new来创建的,都存储在堆内存。 |
| 方法栈 | 方法运行时使用的内存,比如main方法运行,进入方法栈中执行。 |

### 1.6 Java内存分配-一个数组内存图

![1591007817165](.\img\1591007817165.png)

### 1.7 两个数组内存图

![1591007925899](.\img\1591007925899.png)

### 1.8 多个数组指向相同内存图

![1591007957052](.\img\1591007957052.png)

### 1.9 数组的静态初始化

#### 1.9.1 什么是静态初始化

​ 在创建数组时,直接将元素确定

#### 1.9.2 静态初始化格式

- 完整版格式

```java
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,...};
```

- 简化版格式

```java
数据类型[] 数组名 = {元素1,元素2,...};
```

#### 1.9.3示例代码

```java
package com.itheima.array2;

public class Demo1Array {
/*
数组静态初始化 : 初始化时指定每个数组元素的初始值,由系统决定数组长度

完整格式:
数据类型[] 数组名 = new 数据类型[]{数据1,数据2,数据3...};
简化格式:
数据类型[] 数组名 = {数据1,数据2,数据3...};
*/
public static void main(String[] args) {
// 数据类型[] 数组名 = new 数据类型[]{数据1,数据2,数据3...};
int[] arr = new int[]{11,22,33};
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);

// 数据类型[] 数组名 = {数据1,数据2,数据3...};
int[] arr2 = {44,55,66};
System.out.println(arr2);
System.out.println(arr2[0]);
System.out.println(arr2[1]);
System.out.println(arr2[2]);

}
}
```

### 1.10 数组操作的两个常见问题

#### 1.10.1 索引越界异常

- 出现原因

```java
public class ArrayDemo {
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr[3]);
}
}
```

数组长度为3,索引范围是0~2,但是我们却访问了一个3的索引。

程序运行后,将会抛出ArrayIndexOutOfBoundsException 数组越界异常。在开发中,数组的越界异常是不能出现的,一旦出现了,就必须要修改我们编写的代码。

- 解决方案

将错误的索引修改为正确的索引范围即可!

#### 1.10.2 空指针异常

- 出现原因

```java
public class ArrayDemo {
public static void main(String[] args) {
int[] arr = new int[3];

//把null赋值给数组
arr = null;
System.out.println(arr[0]);
}
}
```

arr = null 这行代码,意味着变量arr将不会在保存数组的内存地址,也就不允许再操作数组了,因此运行的时候会抛出 NullPointerException 空指针异常。在开发中,空指针异常是不能出现的,一旦出现了,就必须要修改我们编写的代码。

- 解决方案

给数组一个真正的堆内存空间引用即可!

### 1.11 数组遍历

- 数组遍历:就是将数组中的每个元素分别获取出来,就是遍历。遍历也是数组操作中的基石。

```java
public class ArrayTest01 {
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
System.out.println(arr[4]);
}
}
```

以上代码是可以将数组中每个元素全部遍历出来,但是如果数组元素非常多,这种写法肯定不行,因此我们需要改造成循环的写法。数组的索引是 0 到 lenght-1 ,可以作为循环的条件出现。

```java
public class ArrayTest01 {
public static void main(String[] args) {
//定义数组
int[] arr = {11, 22, 33, 44, 55};

//使用通用的遍历格式
for(int x=0; x<arr.length; x++) {
System.out.println(arr[x]);
}
}
}
```

### 1.12 数组获取最大值

- 最大值获取:从数组的所有元素中找出最大值。

- 实现思路:

- 定义变量,保存数组0索引上的元素
- 遍历数组,获取出数组中的每个元素
- 将遍历到的元素和保存数组0索引上值的变量进行比较
- 如果数组元素的值大于了变量的值,变量记录住新的值
- 数组循环遍历结束,变量保存的就是数组中的最大值

- 代码实现:

```java
package com.itheima.test;

import java.util.Scanner;

public class Test2Array {
/*
需求: 从数组中查找最大值

int[] arr = {12,45,98,73,60};

实现步骤:
1. 假设数组中的第一个元素为最大值
2. 遍历数组, 获取每一个元素, 准备进行比较
3. 如果比较的过程中, 出现了比max更大的, 让max记录更大的值
4. 循环结束后, 打印最大值.
*/
public static void main(String[] args) {
int[] arr = {12,45,98,73,60};
// 1. 假设数组中的第一个元素为最大值
int max = arr[0];
// 2. 遍历数组, 获取每一个元素, 准备进行比较
for(int i = 1; i < arr.length; i++){
// 3. 如果比较的过程中, 出现了比max更大的, 让max记录更大的值
if(arr[i] > max){
max = arr[i];
}
}
// 4. 循环结束后, 打印最大值.
System.out.println("max:" + max);
}
}

```

### 1.13 数组元素求和

- 需求:键盘录入5个整数,存储到数组中,并对数组求和

- 思路:
1.创建键盘录入对象,准备键盘录入
2.定义一个求和变量,准备记录累加后的结果
3.动态初始化一个长度为5的int数组,准备存储键盘录入的数值
4.将键盘录入的数值存储到数组中
5.遍历数组,取出每一个元素,并求和
6.输出总和

- 代码实现:

```java
package com.itheima.test;

import java.util.Scanner;

public class Test3Array {
/*
需求:键盘录入5个整数,存储到数组中,并对数组求和

思路:
1.创建键盘录入对象,准备键盘录入
2.定义一个求和变量,准备记录累加后的结果
3.动态初始化一个长度为5的int数组,准备存储键盘录入的数值
4.将键盘录入的数值存储到数组中
5.遍历数组,取出每一个元素,并求和
6.输出总和
*/
public static void main(String[] args) {
// 1.创建键盘录入对象,准备键盘录入
Scanner sc = new Scanner(System.in);
// 2.定义一个求和变量,准备记录累加后的结果
int sum = 0;
// 3.动态初始化一个长度为5的int数组,准备存储键盘录入的数值
int[] arr = new int[5];
// 4.将键盘录入的数值存储到数组中
for(int i = 0; i < arr.length; i++){
System.out.println("请输入第" + (i+1) + "个整数:");
//arr[i] = 10;
arr[i] = sc.nextInt();
}

// 5.遍历数组,取出每一个元素,并求和
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}

// 6.输出总和
System.out.println("sum:" + sum);

}
}

```

### 1.14 数组基本查找【应用】

- 需求:
已知一个数组 arr = {19, 28, 37, 46, 50}; 键盘录入一个数据,查找该数据在数组中的索引,并在控
制台输出找到的索引值。

- 思路:
1.定义一个数组,用静态初始化完成数组元素的初始化
2.键盘录入要查找的数据,用一个变量接收
3.定义一个索引变量,初始值为-1
4.遍历数组,获取到数组中的每一个元素
5.拿键盘录入的数据和数组中的每一个元素进行比较,如果值相同,就把该值对应的索引赋值给索引变量,并结束循环
6.输出索引变量

- 代码实现:

```java
public static void main(String[] args) {
// 1.定义一个数组,用静态初始化完成数组元素的初始化
int[] arr = {19, 28, 37, 46, 50};
// 2.键盘录入要查找的数据,用一个变量接收
Scanner sc = new Scanner(System.in);
System.out.println("请输入您要查找的元素:");
int num = sc.nextInt();
// 3.定义一个索引变量,初始值为-1
// 假设要查找的数据, 在数组中就是不存在的
int index = -1;
// 4.遍历数组,获取到数组中的每一个元素
for (int i = 0; i < arr.length; i++) {
// 5.拿键盘录入的数据和数组中的每一个元素进行比较,如果值相同,就把该值对应的索引赋值给索引变量,并结束循环
if(num == arr[i]){
// 如果值相同,就把该值对应的索引赋值给索引变量,并结束循环
index = i;
break;
}
}
// 6.输出索引变量
System.out.println(index);
}
}

```

### 1.15 评委打分【应用】

- 需求:在编程竞赛中,有6个评委为参赛的选手打分,分数为0-100的整数分。
选手的最后得分为:去掉一个最高分和一个最低分后 的4个评委平均值 (不考虑小数部分)。

- 思路:
1.定义一个数组,用动态初始化完成数组元素的初始化,长度为6
2.键盘录入评委分数
3.由于是6个评委打分,所以,接收评委分数的操作,用循环
4.求出数组最大值
5.求出数组最小值
6.求出数组总和
7.按照计算规则进行计算得到平均分
8.输出平均分

- 代码实现:

```java
public static void main(String[] args) {
// 1.定义一个数组,用动态初始化完成数组元素的初始化,长度为6
int[] arr = new int[6];
// 2.键盘录入评委分数
Scanner sc = new Scanner(System.in);
// 3.由于是6个评委打分,所以,接收评委分数的操作,用循环
for (int i = 0; i < arr.length; i++) {
System.out.println("请输入第" + (i+1) + "个评委的打分:");
int score = sc.nextInt();
if(score >= 0 && score <= 100){
// 合法的分值
arr[i] = score;
}else{
// 非法的分值
System.out.println("您的打分输入有误, 请检查是否是0-100之间的");
i--;
}
}

// 4.求出数组最大值
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if(max < arr[i]){
max = arr[i];
}
}

// 5.求出数组最小值
int min = arr[0];
for (int i = 1; i < arr.length; i++) {
if(min > arr[i]){
min = arr[i];
}
}

// 6.求出数组总和
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}

// 7.按照计算规则进行计算得到平均分
int avg = (sum - max - min ) / 4;

// 8.输出平均分
System.out.println(avg);
}
}
```

## 1. 方法概述

### 1.1 方法的概念

​ 方法(method)是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集

* 注意:
* 方法必须先创建才可以使用,该过程成为方法定义
* 方法创建后并不是直接可以运行的,需要手动使用后,才执行,该过程成为方法调用

## 2. 方法的定义和调用

### 2.1 无参数方法定义和调用

* 定义格式:

```java
public static void 方法名 ( ) {
// 方法体;
}
```

* 范例:

```java
public static void method ( ) {
// 方法体;
}
```

* 调用格式:

```java
方法名();
```

* 范例:

```java
method();
```

* 注意:

​ 方法必须先定义,后调用,否则程序将报错

### 2.2 方法的调用过程

* 总结:每个方法在被调用执行的时候,都会进入栈内存,并且拥有自己独立的内存空间,方法内部代码调用完毕之后,会从栈内存中弹栈消失。

 

### 2.3 方法练习-奇偶数判断

* 需求:判断一个数是奇数还是偶数
* 代码:

```java
public class Demo1Method {
/*

带参数方法的定义格式:
public static void 方法名 ( 参数 ) { … … }
public static void 方法名 ( 数据类型 变量名 ) { … … }

带参数方法的调用格式:
方法名 ( 参数 ) ;
方法名 ( 变量名/常量值 ) ;

tips: 参数可以是一个, 也可以是多个.

需求: 判断一个数是奇数还是偶数
*/
public static void main(String[] args) {
isEvenNumber(10);
}

public static void isEvenNumber(int num){
if(num % 2 == 0){
System.out.println("偶数");
}else{
System.out.println("奇数");
}
}
}
```

## 3. 带参数方法的定义和调用

### 3.1 带参数方法定义和调用

* 定义格式:

参数:由数据类型和变量名组成 - 数据类型 变量名

参数范例:int a

```java
public static void 方法名 (参数1) {
方法体;
}

public static void 方法名 (参数1, 参数2, 参数3...) {
方法体;
}
```

* 范例:

```java
public static void isEvenNumber(int number){
...
}
public static void getMax(int num1, int num2){
...
}
```

* 注意:

方法定义时,参数中的数据类型与变量名都不能缺少,缺少任意一个程序将报错

方法定义时,多个参数之间使用逗号( ,)分隔

* 调用格式:

```java
方法名(参数);

方法名(参数1,参数2);
```

* 范例:

```java
isEvenNumber(10);

getMax(10,20);
```

* 方法调用时,参数的数量与类型必须与方法定义中的设置相匹配,否则程序将报错

### 3.2 形参和实参

1. 形参:方法定义中的参数

​ 等同于变量定义格式,例如:int number

2. 实参:方法调用中的参数

​ 等同于使用变量或常量,例如: 10 number

### 3.3 带参数方法的练习-打印n-m之间所有的奇数

* 需求:设计一个方法(print) 用于打印 n 到 m 之间所有的奇数
* 思路:

​ 1:定义方法,名称为print
2:为方法添加两个int类型的形参,准备接受调用者传递过来的实参
3:方法中设计for循环,循环从n开始,到m结束
4:循环中加入if判断,是奇数,则打印
5:main方法中调用print方法,传入两个实际参数
* 代码:

```java
package com.itheima.method2;

public class Demo2Method {
public static void main(String[] args) {
// 5:main方法中调用print方法,传入两个实际参数
print(20,10);
}

//1:定义方法,名称为print
// 2:为方法添加两个int类型的形参,准备接受调用者传递过来的实参
public static void print(int n, int m){
System.out.println(n + "到" + m + "之间的奇数为:");
// 3:方法中设计for循环,循环从n开始,到m结束
for(int i = 20; i <= 10; i++){
// 4:循环中加入if判断,是奇数,则打印
if(i % 2 == 1){
System.out.println(i);
}
}
}

}
```

## 4. 带返回值方法的定义和调用

### 4.1 带返回值方法定义和调用(掌握)

* 定义格式

```java
public static 数据类型 方法名 ( 参数 ) {
return 数据 ;
}
```

* 范例

```java
public static boolean isEvenNumber( int number ) {
return true ;
}
public static int getMax( int a, int b ) {
return 100 ;
}
```

* 注意:
* 方法定义时return后面的返回值与方法定义上的数据类型要匹配,否则程序将报错

* 调用格式

```java
方法名 ( 参数 ) ;
数据类型 变量名 = 方法名 ( 参数 ) ;
```

* 范例

```java
isEvenNumber ( 5 ) ;
boolean flag = isEvenNumber ( 5 );
```

* 注意:
* 方法的返回值通常会使用变量接收,否则该返回值将无意义

### 4.2 带返回值方法的练习-求两个数的最大值(应用)

* 需求:设计一个方法可以获取两个数的较大值,数据来自于参数

* 思路:

1. 定义一个方法,声明两个形参接收计算的数值,求出结果并返回
2. 使用 if 语句 得出 a 和 b 之间的最大值,根据情况return具体结果
3. 在main()方法中调用定义好的方法并使用 【 变量保存 】

* 代码:

```java
/*
需求:设计一个方法可以获取两个数的较大值,数据来自于参数

1. 定义一个方法,声明两个形参接收计算的数值,求出结果并返回
2. 使用 if 语句 得出 a 和 b 之间的最大值,根据情况return具体结果
3. 在main()方法中调用定义好的方法并使用 【 变量保存 】
*/
public static void main(String[] args) {
// 3. 在main()方法中调用定义好的方法并使用 【 变量保存 】
System.out.println(getMax(10,20)); // 输出调用

int result = getMax(10,20);
System.out.println(result);

for(int i = 1; i <= result; i++){
System.out.println("HelloWorld");
}

}

// 方法可以获取两个数的较大值
public static int getMax(int a, int b){
if(a > b){
return a;
}else{
return b;
}
}

}

```

## 5. 方法的注意事项

### 5.1 方法的通用格式(掌握)

- 格式:

```java
public static 返回值类型 方法名(参数) {
方法体;
return 数据 ;
}
```

- 解释:

- public static 修饰符,目前先记住这个格式

返回值类型 方法操作完毕之后返回的数据的数据类型

​ 如果方法操作完毕,没有数据返回,这里写void,而且方法体中一般不写return

方法名 调用方法时候使用的标识

参数 由数据类型和变量名组成,多个参数之间用逗号隔开

方法体 完成功能的代码块

return 如果方法操作完毕,有数据返回,用于把数据返回给调用者

- 定义方法时,要做到两个明确

- 明确返回值类型:主要是明确方法操作完毕之后是否有数据返回,如果没有,写void;如果有,写对应的数据类型
- 明确参数:主要是明确参数的类型和数量

- 调用方法时的注意:

- void类型的方法,直接调用即可
- 非void类型的方法,推荐用变量接收调用

 

### 5.2 方法的注意事项

* 方法不能嵌套定义

* 示例代码:

```java
public class MethodDemo {
public static void main(String[] args) {

}

public static void methodOne() {
public static void methodTwo() {
// 这里会引发编译错误!!!
}
}
}
```

* void表示无返回值,可以省略return,也可以单独的书写return,后面不加数据

* 示例代码:

```java
public class MethodDemo {
public static void main(String[] args) {

}
public static void methodTwo() {
//return 100; 编译错误,因为没有具体返回值类型
return;
//System.out.println(100); return语句后面不能跟数据或代码
}
}
```

## 6. 方法重载

### 6.1 方法重载

* 方法重载概念

方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载

* 多个方法在同一个类中
* 多个方法具有相同的方法名
* 多个方法的参数不相同,类型不同或者数量不同

* 注意:

* 重载仅对应方法的定义,与方法的调用无关,调用方式参照标准格式
* 重载仅针对同一个类中方法的名称与参数进行识别,与返回值无关,换句话说不能通过返回值来判定两个方法是否相互构成重载

* 正确范例:

```java
public class MethodDemo {
public static void fn(int a) {
//方法体
}
public static int fn(double a) {
//方法体
}
}

public class MethodDemo {
public static float fn(int a) {
//方法体
}
public static int fn(int a , int b) {
//方法体
}
}
```

* 错误范例:

```java
public class MethodDemo {
public static void fn(int a) {
//方法体
}
public static int fn(int a) { /*错误原因:重载与返回值无关*/
//方法体
}
}

public class MethodDemo01 {
public static void fn(int a) {
//方法体
}
}
public class MethodDemo02 {
public static int fn(double a) { /*错误原因:这是两个类的两个fn方法*/
//方法体
}
}
```

### 6.2 方法重载练习

* 需求:使用方法重载的思想,设计比较两个整数是否相同的方法,兼容全整数类型(byte,short,int,long)

* 思路:

​ ①定义比较两个数字的是否相同的方法compare()方法,参数选择两个int型参数

​ ②定义对应的重载方法,变更对应的参数类型,参数变更为两个long型参数

​ ③定义所有的重载方法,两个byte类型与两个short类型参数

​ ④完成方法的调用,测试运行结果

* 代码:

```java
public class MethodTest {
public static void main(String[] args) {
//调用方法
System.out.println(compare(10, 20));
System.out.println(compare((byte) 10, (byte) 20));
System.out.println(compare((short) 10, (short) 20));
System.out.println(compare(10L, 20L));
}

//int
public static boolean compare(int a, int b) {
System.out.println("int");
return a == b;
}

//byte
public static boolean compare(byte a, byte b) {
System.out.println("byte");
return a == b;
}

//short
public static boolean compare(short a, short b) {
System.out.println("short");
return a == b;
}

//long
public static boolean compare(long a, long b) {
System.out.println("long");
return a == b;
}

}
```

## 7. 方法的参数传递

### 7.1 方法参数传递基本类型(理解)

* 测试代码:

```java
package com.itheima.param;

public class Test1 {
/*
方法参数传递为基本数据类型 :

传入方法中的, 是具体的数值.
*/
public static void main(String[] args) {
int number = 100;
System.out.println("调用change方法前:" + number);
change(number);
System.out.println("调用change方法后:" + number);
}

public static void change(int number) {
number = 200;
}
}

```

* 结论:

* 基本数据类型的参数,形式参数的改变,不影响实际参数

* 结论依据:

* 每个方法在栈内存中,都会有独立的栈空间,方法运行结束后就会弹栈消失

### 7.2 方法参数传递引用类型

* 测试代码:

```java
package com.itheima.param;

public class Test2 {
/*
方法参数传递为引用数据类型 :

传入方法中的, 是内存地址.
*/
public static void main(String[] args) {
int[] arr = {10, 20, 30};
System.out.println("调用change方法前:" + arr[1]);
change(arr);
System.out.println("调用change方法后:" + arr[1]);
}

public static void change(int[] arr) {
arr[1] = 200;
}
}
```

* 结论:

* 对于引用类型的参数,形式参数的改变,影响实际参数的值

* 结论依据:

* 引用数据类型的传参,传入的是地址值,内存中会造成两个引用指向同一个内存的效果,所以即使方法弹栈,堆内存中的数据也已经是改变后的结果

### 7.3 数组遍历

* 需求:设计一个方法用于数组遍历,要求遍历的结果是在一行上的。例如:[11, 22, 33, 44, 55]

* 思路:

* 因为要求结果在一行上输出,所以这里需要在学习一个新的输出语句System.out.print(“内容”);

System.out.println(“内容”); 输出内容并换行

System.out.print(“内容”); 输出内容不换行

System.out.println(); 起到换行的作用

* 定义一个数组,用静态初始化完成数组元素初始化

* 定义一个方法,用数组遍历通用格式对数组进行遍历

* 用新的输出语句修改遍历操作

* 调用遍历方法

* 代码:

```java
package com.itheima.test;

public class Test1 {
/*
需求:设计一个方法用于数组遍历,要求遍历的结果是在一行上的。例如:[11, 22, 33, 44, 55]
思路:
1.定义一个数组,用静态初始化完成数组元素初始化
2.定义一个方法,对数组进行遍历
3.遍历打印的时候,数据不换行
4.调用遍历方法
*/
public static void main(String[] args) {
// 1.定义一个数组,用静态初始化完成数组元素初始化
int[] arr = {11, 22, 33, 44, 55};
// 4.调用遍历方法
printArray(arr);

System.out.println("另外一段代码逻辑 ");
}

/*
2.定义一个方法,对数组进行遍历

1, 参数 int[] arr
2, 返回值类型 void
*/
public static void printArray(int[] arr){

System.out.print("[");

for (int i = 0; i < arr.length; i++) {

if(i == arr.length -1){
// 如果满足条件, 说明是最后一个元素, 最后一个元素, 特殊处理
System.out.println(arr[i] + "]");
}else{
// 3.遍历打印的时候,数据不换行
System.out.print(arr[i] + ", ");
}

}
}
}

```

### 7.4 数组最大值

* 需求:设计一个方法用于获取数组中元素的最大值

* 思路:

* ①定义一个数组,用静态初始化完成数组元素初始化
* ②定义一个方法,用来获取数组中的最大值,最值的认知和讲解我们在数组中已经讲解过了
* ③调用获取最大值方法,用变量接收返回结果
* ④把结果输出在控制台

* 代码:

```java
package com.itheima.test;

public class Test2 {
/*
需求:设计一个方法用于获取数组中元素的最大值

思路:
1.定义一个数组,用静态初始化完成数组元素初始化
2.定义一个方法,用来获取数组中的最大值
3.调用获取最大值方法,用变量接收返回结果
4.把结果输出在控制台
*/
public static void main(String[] args) {
// 1.定义一个数组,用静态初始化完成数组元素初始化
int[] arr = {11, 55, 22, 44, 33};
// 3.调用获取最大值方法,用变量接收返回结果
int max = getMax(arr);
// 4.把结果输出在控制台
System.out.println(max);
}

/*
2.定义一个方法,用来获取数组中的最大值

1, 参数 int[] arr
2, 返回值类型 int
*/
public static int getMax(int[] arr){
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if(max < arr[i]){
max = arr[i];
}
}
return max;
}
}

```

 

### 7.5 方法同时获取数组最大值和最小值

- 需求:设计一个方法,该方法能够同时获取数组的最大值,和最小值

- 注意: return语句, 只能带回一个结果.

- 代码:

```java
public class Test3 {
/*
需求:设计一个方法,该方法能够同时获取数组的最大值,和最小值

注意: return语句, 只能带回一个结果.
*/
public static void main(String[] args) {

int[] arr = {11,55,33,22,44};

int[] maxAndMin = getMaxAndMin(arr);

System.out.println(maxAndMin[0]);
System.out.println(maxAndMin[1]);

}

public static int[] getMaxAndMin(int[] arr){
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if(max < arr[i]){
max = arr[i];
}
}

int min = arr[0];
for (int i = 1; i < arr.length; i++) {
if(min > arr[i]){
min = arr[i];
}
}

int[] maxAndMin = {min, max};

return maxAndMin;
}
}

```

## 1.Debug模式

### 1.1 什么是Debug模式

是供程序员使用的程序调试工具,它可以用于查看程序的执行流程,也可以用于追踪程序执行过程来调试程序。

### 1.2 Debug介绍与操作流程

- 如何加断点

- 选择要设置断点的代码行,在行号的区域后面单击鼠标左键即可

- 如何运行加了断点的程序

- 在代码区域右键Debug执行

- 看哪里

- 看Debugger窗口

- 看Console窗口

- 点哪里

- 点Step Into (F7)这个箭头,也可以直接按F7

- 如何删除断点

- 选择要删除的断点,单击鼠标左键即可

- 如果是多个断点,可以每一个再点击一次。也可以一次性全部删除

## 2. 进制的介绍与书写格式

### 2.1 进制的介绍与书写格式

代码 :

```java
public class Demo1 {
/*
十进制:Java中,数值默认都是10进制,不需要加任何修饰。
二进制:数值前面以0b开头,b大小写都可以。
八进制:数值前面以0开头。
十六进制:数值前面以0x开头,x大小写都可以。

注意: 书写的时候, 虽然加入了进制的标识, 但打印在控制台展示的都是十进制数据.
*/
public static void main(String[] args) {
System.out.println(10);
System.out.println("二进制数据0b10的十进制表示为:" + 0b10);
System.out.println("八进制数据010的十进制表示为:" + 010);
System.out.println("十六进制数据0x10的十进制表示为:" + 0x10);
}
}
```

### 2.2 任意进制到十进制的转换

![1590937009286](.\img\1590937009286.png)

![1590937024104](.\img\1590937024104.png)

 

 

### 2.3 进制转换-十进制到任意进制转换

​ **2.3.1 : 十进制到二进制的转换**

​ 公式:除基取余使用源数据,不断的除以基数(几进制,基数就是几)得到余数,直到商为0,再将余数倒着拼起来即可。

​ 需求:将十进制数字11,转换为2进制。

​ 实现方式:源数据为11,使用11不断的除以基数,也就是2,直到商为0。

![1590936221838](.\img\1590936221838.png)

​ **2.3.2 : 十进制到十六进制的转换**

​ 公式:除基取余使用源数据,不断的除以基数(几进制,基数就是几)得到余数,直到商为0,再将余数倒着拼起来即可。

​ 需求:将十进制数字60,转换为16进制。

​ 实现方式:源数据为60,使用60不断的除以基数,也就是16,直到商为0。

![1590936342865](.\img\1590936342865.png)

​ 结论:十进制到任意进制的转换

​ 公式:除基取余使用源数据,不断的除以基数(几进制,基数就是几)得到余数,直到商为0,再将余数倒着 拼起来即可

### 2.4 快速进制转换法

​ 8421码:

​ 8421码又称BCD码,是BCD代码中最常用的一种BCD: (Binary-Coded Decimal‎) 二进制码十进制数在这种编码方式中,每一位二进制值的1都是代表一个固定数值,把每一位的1代表的十进制数加起来得到的结果就是它所代表的十进制数。

​ ![1590936493344](.\img\1590936493344.png)

 

![1590936529957](.\img\1590936529957.png)

![1590936548060](.\img\1590936548060.png)

### 2.5 原码反码补码

前言 : 计算机中的数据,都是以二进制补码的形式在运算,而补码则是通过反码和原码推算出来的

**原码 **:(可直观看出数据大小)

就是二进制定点表示法,即最高位为符号位,【0】表示正,【1】表示负,其余位表示数值的大小。

通过一个字节表示+7和-7,代码:byte b1 = 7; byte b2 = -7;一个字节等于8个比特位,也就是8个二进制位

0(符号位) 0000111

1(符号位) 0000111

**反码 :** 正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外。

**补码 :** (数据以该状态进行运算)正数的补码与其原码相同;负数的补码是在其反码的末位加1。

 

![1590936726746](.\img\1590936726746.png)

![1590936745245](.\img\1590936745245.png)

 

### 2.6 位运算-基本位运算符

```java
package com.itheima.demo;

public class Demo2 {
/*
位运算:

位运算符指的是二进制位的运算,先将十进制数转成二进制后再进行运算。
在二进制位运算中,1表示true,0表示false。

& 位与 : 遇false则false, 遇0则0

00000000 00000000 00000000 00000110 // 6的二进制
& 00000000 00000000 00000000 00000010 // 2的二进制
-----------------------------------------
00000000 00000000 00000000 00000010 // 结果: 2

| 位或 : 遇true则true, 遇1则1

^ 位异或 : 相同为false, 不同为true

~ 取反 : 全部取反, 0变1, 1变0 (也包括符号位)

00000000 00000000 00000000 00000110 // 6的二进制补码
~ 11111111 11111111 11111111 11111001

- 1 // -1求反码
------------------------------------
11111111 11111111 11111111 11111000 // 反码推原码

10000000 00000000 00000000 00000111 // -7
*/
public static void main(String[] args) {
System.out.println(6 & 2);
System.out.println(~6);
}
}

```

 

### 2.7 位运算-位移运算符

**位运算概述 :** 位运算符指的是二进制位的运算,先将十进制数转成二进制后再进行运算。在二进制位运算中,1表示true,0表示false。

**位运算符介绍 :** ![1590937235620](.\img\1590937235620.png)

**代码 :**

```java
package com.itheima.demo;

public class Demo3 {
/*
位移运算符:

<< 有符号左移运算,二进制位向左移动, 左边符号位丢弃, 右边补齐0
运算规律: 向左移动几位, 就是乘以2的几次幂

12 << 2

(0)0000000 00000000 00000000 000011000 // 12的二进制

-----------------------------------------------------------------------------
>> 有符号右移运算,二进制位向右移动, 使用符号位进行补位
运算规律: 向右移动几位, 就是除以2的几次幂

000000000 00000000 00000000 0000001(1) // 3的二进制

-----------------------------------------------------------------------------

>>> 无符号右移运算符, 无论符号位是0还是1,都补0

010000000 00000000 00000000 00000110 // -6的二进制

*/
public static void main(String[] args) {
System.out.println(12 << 1); // 24
System.out.println(12 << 2); // 48

}
}

```

```java
package com.itheima.demo;

public class Demo4 {
/*
^ 运算符的特点

一个数, 被另外一个数, 异或两次, 该数本身不变
*/
public static void main(String[] args) {
System.out.println(10 ^ 5 ^ 10);
}
}

```

## 3.基础练习

### 3.1 数据交换

**案例需求**

​ 已知两个整数变量a = 10,b = 20,使用程序实现这两个变量的数据交换
最终输出a = 20,b = 10;

**代码实现**

```java
package com.itheima.test;

public class Test1 {
/*
需求:已知两个整数变量a = 10,b = 20,使用程序实现这两个变量的数据交换
最终输出a = 20,b = 10;

思路:
1. 定义一个三方变量temp,将a原本记录的值,交给temp记录 (a的值,不会丢了)
2. 使用 a 变量记录 b 的值,(第一步交换完毕,b的值也丢不了了)
3. 使用 b 变量记录 temp的值,也就是a原本的值 (交换完毕)
4. 输出 a 和 b 变量即可
*/
/*
动态初始化格式:

数据类型[][] 变量名 = new 数据类型[m][n];
m表示这个二维数组,可以存放多少个一维数组
n表示每一个一维数组,可以存放多少个元素
*/
public static void main(String[] args) {
int a = 10;
int b = 20;

// 将a原本记录的值,交给temp记录 (a的值,不会丢了)
int temp = a;
// 用 a 变量记录 b 的值,(第一步交换完毕,b的值也丢不了了)
a = b;
// 使用 b 变量记录 temp的值,也就是a原本的值 (交换完毕)
b = temp;

// 输出 a 和 b 变量即可
System.out.println("a=" + a);
System.out.println("b=" + b);
}
}
```

### 3.2 数组反转【应用】

**案例需求 :**

​ 已知一个数组 arr = {19, 28, 37, 46, 50}; 用程序实现把数组中的元素值交换,

​ 交换后的数组 arr = {50, 46, 37, 28, 19}; 并在控制台输出交换后的数组元素

**实现步骤 :**

1. 定义两个变量, start和end来表示开始和结束的指针.

2. 确定交换条件, start < end 允许交换
3. 循环中编写交换逻辑代码
4. 每一次交换完成, 改变两个指针所指向的索引 start++, end--
5. 循环结束后, 遍历数组并打印, 查看反转后的数组

**代码实现 :**

```java
package com.itheima.test;

public class Test2 {
/*
需求:已知一个数组 arr = {19, 28, 37, 46, 50}; 用程序实现把数组中的元素值交换,
交换后的数组 arr = {50, 46, 37, 28, 19}; 并在控制台输出交换后的数组元素。

步骤:
1. 定义两个变量, start和end来表示开始和结束的指针.
2. 确定交换条件, start < end 允许交换
3. 循环中编写交换逻辑代码
4. 每一次交换完成, 改变两个指针所指向的索引 start++, end--
5. 循环结束后, 遍历数组并打印, 查看反转后的数组
*/
public static void main(String[] args) {
int[] arr = {19, 28, 37, 46, 50};
// 1. 定义两个变量, start和end来表示开始和结束的指针.
int start = 0;
int end = arr.length -1;
// 2. 确定交换条件, start < end 允许交换
// 4. 每一次交换完成, 改变两个指针所指向的索引 start++, end--
// for(int start = 0, end = arr.length -1; start < end; start++, end--)
for( ; start < end; start++, end--){
// 3. 循环中编写交换逻辑代码
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
}

for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}

```

### 3.3 二维数组概述

​ **概述 :** 二维数组也是一种容器,不同于一维数组,该容器存储的都是一维数组容器

### 3.4 二维数组动态初始化

```java
动态初始化格式:

数据类型[][] 变量名 = new 数据类型[m][n];
m表示这个二维数组,可以存放多少个一维数组
n表示每一个一维数组,可以存放多少个元素
```

```java
package com.itheima.demo;

public class Demo1Array {
/*
动态初始化格式:

数据类型[][] 变量名 = new 数据类型[m][n];
m表示这个二维数组,可以存放多少个一维数组
n表示每一个一维数组,可以存放多少个元素
*/
public static void main(String[] args) {
// 数据类型[][] 变量名 = new 数据类型[m][n];
int[][] arr = new int[3][3];
/*
[[I@10f87f48

@ : 分隔符
10f87f48 : 十六进制内存地址
I : 数组中存储的数据类型
[[ : 几个中括号就代表的是几维数组
*/
System.out.println(arr);

/*
二维数组存储一维数组的时候, 存储的是一维数组的内存地址
*/
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);

System.out.println(arr[0][0]);
System.out.println(arr[1][1]);
System.out.println(arr[2][2]);

// 向二维数组中存储元素
arr[0][0] = 11;
arr[0][1] = 22;
arr[0][2] = 33;

arr[1][0] = 11;
arr[1][1] = 22;
arr[1][2] = 33;

arr[2][0] = 11;
arr[2][1] = 22;
arr[2][2] = 33;

// 从二维数组中取出元素并打印
System.out.println(arr[0][0]);
System.out.println(arr[0][1]);
System.out.println(arr[0][2]);
System.out.println(arr[1][0]);
System.out.println(arr[1][1]);
System.out.println(arr[1][2]);
System.out.println(arr[2][0]);
System.out.println(arr[2][1]);
System.out.println(arr[2][2]);
}
}
```

### 3.5 二维数组访问元素的细节问题

问题 : 二维数组中存储的是一维数组, 那能不能存入 [提前创建好的一维数组] 呢 ?

答 : 可以的

#### 代码实现

```java
package com.itheima.demo;

public class Demo2Array {
/*
问题: 二维数组中存储的是一维数组, 那能不能存入 [提前创建好的一维数组] 呢 ?
答 : 可以的
*/
public static void main(String[] args) {
int[] arr1 = {11,22,33};
int[] arr2 = {44,55,66};
int[] arr3 = {77,88,99,100};

int[][] arr = new int[3][3];

arr[2][3] = 100;

arr[0] = arr1;
arr[1] = arr2;
arr[2] = arr3;

System.out.println(arr[1][2]);
System.out.println(arr[2][3]);
}
}
```

### 3.6 二维数组静态初始化

**完整格式 :** 数据类型[][] 变量名 = new 数据类型[][]{ {元素1, 元素2...} , {元素1, 元素2...}

**简化格式 :** 数据类型[][] 变量名 = { {元素1, 元素2...} , {元素1, 元素2...} ...};

**代码实现 : **

```java
package com.itheima.demo;

public class Demo3Array {
/*
完整格式:数据类型[][] 变量名 = new 数据类型[][]{ {元素1, 元素2...} , {元素1, 元素2...} ...};

简化格式: 数据类型[][] 变量名 = { {元素1, 元素2...} , {元素1, 元素2...} ...};
*/
public static void main(String[] args) {
int[] arr1 = {11,22,33};
int[] arr2 = {44,55,66};

int[][] arr = {{11,22,33}, {44,55,66}};
System.out.println(arr[0][2]);

int[][] array = {arr1,arr2};
System.out.println(array[0][2]);
}
}

```

### 3.7 二维数组遍历

**需求 :**

​ 已知一个二维数组 arr = {{11, 22, 33}, {33, 44, 55}};

​ 遍历该数组,取出所有元素并打印

**步骤 :**

1. 遍历二维数组,取出里面每一个一维数组
2. 在遍历的过程中,对每一个一维数组继续完成遍历,获取内部存储的每一个元素

**代码实现 :**

```java
package com.itheima.test;

public class Test1 {
/*
需求:

已知一个二维数组 arr = {{11, 22, 33}, {33, 44, 55}};
遍历该数组,取出所有元素并打印

步骤:
1. 遍历二维数组,取出里面每一个一维数组
2. 在遍历的过程中,对每一个一维数组继续完成遍历,获取内部存储的每一个元素
*/
public static void main(String[] args) {
int[][] arr = {{11, 22, 33}, {33, 44, 55}};

// 1. 遍历二维数组,取出里面每一个一维数组
for (int i = 0; i < arr.length; i++) {
//System.out.println(arr[i]);
// 2. 在遍历的过程中,对每一个一维数组继续完成遍历,获取内部存储的每一个元素
//int[] temp = arr[i];
for (int j = 0; j < arr[i].length; j++) {
System.out.println(arr[i][j]);
}
}
}
}
```

### 3.8 二维数组求和

**需求 :**

某公司季度和月份统计的数据如下:单位(万元)
第一季度:22,66,44
第二季度:77,33,88
第三季度:25,45,65
第四季度:11,66,99

**步骤 :**

1. 定义求和变量,准备记录最终累加结果
2. 使用二维数组来存储数据,每个季度是一个一维数组,再将4个一维数组装起来
3. 遍历二维数组,获取所有元素,累加求和
4. 输出最终结果

**代码实现 :**

```java
package com.itheima.test;

public class Test2 {
/*
需求:
某公司季度和月份统计的数据如下:单位(万元)
第一季度:22,66,44
第二季度:77,33,88
第三季度:25,45,65
第四季度:11,66,99

步骤:
1. 定义求和变量,准备记录最终累加结果
2. 使用二维数组来存储数据,每个季度是一个一维数组,再将4个一维数组装起来
3. 遍历二维数组,获取所有元素,累加求和
4. 输出最终结果
*/
public static void main(String[] args) {
// 1. 定义求和变量,准备记录最终累加结果
int sum = 0;
// 2. 使用二维数组来存储数据,每个季度是一个一维数组,再将4个一维数组装起来
int[][] arr = { {22,66,44} , {77,33,88} , {25,45,65} , {11,66,99}};
// 3. 遍历二维数组,获取所有元素,累加求和
for (int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++){
sum += arr[i][j];
}
}
// 4. 输出最终结果
System.out.println(sum);
}
}
```

未经允许不得转载:OZ分享-吉家大宝官方博客 » Java基础语法笔记

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

置顶文章