Java 基础(上篇)

Java 基础(上篇)


内容概要:

开启 Java 之门

Java 语言概述

什么是 Java 语言

Java 语言是美国的 Sun 公司(Stanford University Network) 在 1995 年推出的高级的编程语言。所谓编程语言,是计算机的语言,人们可以使用编程语言对计算机下达命令,让计算机完成人们需要的功能。

Java 语言发展史

Java 发展史:
1995年发布Java 1.0版本 1997年发布Java 1.1版本 1998年发布Java 1.2版本 2000年发布Java 1.3版本 2002年发布Java 1.4版本 2004年发布Java 1.5版本 2006年发布Java 1.6版本
2009年 Oracle 甲骨文公司收购 Sun 公司 2011年发布Java 1.7版本(Oracle 公司发布)
2014年发布Java 1.8版本 2017年发布Java 9.0版本 2018年发布Java 10版本 …

Java 能干什么

Java 语言主要应用在互联网程序的后台开发领域。常见的互联网程序比如天猫、京东、物流系统、网银系统等,以及服务器后台处理大数据的存储、查询、数据挖掘等也有很多应用。例如下图:

计算机基础

认识进制

计算机中的数据不同于我们生活中的数据,在生活中,我们采用 十进制数 计数,而在计算机中,全部都采用了 二进制数 表示,它只包含 0、1 两个数,逢二进一。例如:1 + 1 = 10 。每一个 0 或者每一个 1 ,叫做一个 bit(比特)表示信息的最小单位

进制转换方法:
十进制数据转成二进制数据:使用除以 2 获取余数的方式 二进制数据转成十进制数据:使用 8421 编码的方式

各种进制的表示形式

1
2
3
4
5
6
public static void main(String[] args) {
System.out.println("二进制100的大小:\t" + 0B100); // 二进制表示形式前面加0B(B可以大写,也可以小写)
System.out.println("八进制100的大小:\t" + 0100); // 八进制表示形式前面加0
System.out.println("十进制100的大小:\t" + 100); // 十进制直接输出
System.out.println("十六进制100大小:\t" + 0X100); // 十六进制前面加0x(X可以大写也可以小写)
}

认识字节

字节 是我们常见的计算机中 最小存储单元 。计算机存储任何的数据,都是以字节的形式存储,右键点击文件属性,我们可以查看文件的字节大小。8 个 bit 表示为 1 个字节 ,写成 1byte 或者 1B

位与字节:
位(bit):一个数字 0 或者一个数字 1,代表一位。 字节(Byte): 8 位是一个字节,这是数据存储的最小单位。
计算机存储单位之间的转换:
1 Byte = 8 bit 1 KB = 1024 Byte 1 MB = 1024 KB 1 GB = 1024 MB 1 TB = 1024 GB 1 PB = 1024 TB 1 EB = 1024 PB 1 ZB = 1024 EB 1 YB = 1024 ZB 1 BB = 1024 YB

常用 DOS 命令

MS-DOS(Microsoft Disk Operating System) ,作为 Java 语言的初学者,学习一些 DOS 命令,会非常有帮助。DOS 是一个早期的操作系统,现在已经被 Windows 系统取代,对于我们开发人员,目前需要在 DOS 中完成一些事情,因此就需要掌握一些必要的命令。

相关操作 命令
进入 DOS 窗口 WIN + R ,输入 cmd 回车
切换盘符 例如切换到 D 盘: D:
进入文件夹 cd 文件夹名称
进入多级文件夹 cd 文件夹1\文件夹2\文件夹3
返回上一级 cd ..
直接回根路径 cd \
查看当前内容 dir
清屏 cls
退出 exit

开发环境搭建

Java 虚拟机

JVM(Java Virtual Machine): Java 虚拟机,简称 JVM ,是运行所有 Java 程序的假想计算机,是 Java 程序的运行环境,是 Java 最具吸引力的特性之一。我们编写的 Java 代码,都运行在其上。

跨平台性: 任何软件的运行,都必须要运行在操作系统之上。 而我们用 Java 编写的软件可以运行在任何的操作系统上,这个特性称为 Java 语言的跨平台特性。该特性是由 JVM 实现的,我们编写的程序运行在 JVM 上,而 JVM 运行在操作系统上

JRE 和 JDK

JRE 和 JDK :
1、JRE (Java Runtime Environment): 是 Java 程序的运行时环境,包含 JVM 和运行时所需要的类库。 2、JDK (Java Development Kit): 是 Java 程序开发工具包,包含 JRE 和编译器等开发工具。

三者关系: JDK > JRE > JVM

JDK 安装图解

第一步: 下载 JDK ,这是 下载网址 ,如下图:

第二步: 安装 JDK 。如下图:




温馨小提示: 到此为止, JDK 安装结束,接下来需要配置环境变量,这样才能使用。
个人推荐配置: 开发工具: IDEAJDK 版本: 11 及以上版本

JAVA_HOME 的配置

首先 win + r 打开命令行,输入 sysdm.cpl ,结果如下图:






然后一直点击 确定 即可。这样,Java 环境就安装配置好了。那么怎么查看呢?打开命令行,使用 java -version 查看版本。有如下结果,就代表环境配置好了,否则配置出错了。结果如下图:

其他教程: 菜鸟教程之 Java 开发环境配置

编写入门程序

开发环境已经搭建完毕了,现在可以开发我们的第一个 Java 程序了。Java 程序开发三步骤:编写代码、编译、运行 。现在,我们来搞定 第一步: 编写代码 。在桌面新建一个 HelloWorld.java 文件,写入如下代码:

1
2
3
4
5
6
7
8
9
public class HelloWorld {
public static void main(String[] args) {
// 在 IDEA 软件中,alt + 4 是 console 的快捷键
System.out.println("******************************");
System.out.println("Hello World!");
System.out.println("This is my first Java program!");
System.out.println("******************************");
}
}

第二步: 编译 HelloWorld.java编译 是指将我们编写的 Java 源文件 翻译成 JVM 认识的 class 文件 。在这个过程中,编译器会检查我们所写的程序是否有错误,有错误就会提示出来,如果没有错误就会编译成功。打开命令行,执行如下命令即进行了编译。如下图:

第三步: 运行代码运行 是指将 字节码文件 交给 JVM 去执行,这样,我们的程序就跑起来了。如下图:

1、小提示:
上述使用命令行编译和运行代码挺麻烦的,了解一下就行了。以后用 IDEA 编译和运行,就不需要用命令行了。
2、关于 main 方法
main 方法: 称为主方法。写法是固定格式不可以更改。main 方法是程序的入口点或起始点,无论我们编写多少程序,JVM 在运行的时候,都会从 main 方法这里开始执行。这里要注意:不要写成 mian ,初学容易写错。

Java 中的注释

注释: 就是对代码的解释和说明。其目的是 让开发人员能够更加轻松地了解代码 。为代码添加注释,是十分必要的,它不影响程序的编译和运行。Java 中有三种注释方式 ,相关介绍如下:

1
2
3
4
5
单行注释      # 单行注释以 // 开头换行结束,单行注释支持嵌套。

多行注释 # 多行注释以 /* 开头,以 */ 结束,多行注释不支持嵌套。

文档注释 # 文档注释以 /** 开始,以 */ 结束,文档注释也不支持嵌套。

单行注释

单行注释以 // 开头换行结束,单行注释支持嵌套。

1
2
3
4
5
6
7
// 定义一个变量 key
int key = 10;

// 定义一个方法,实现两数相加
public static void add(int a, int b){
return a + b;
}

多行注释

多行注释以 /* 开头,以 */ 结束,多行注释不支持嵌套。

1
2
3
4
5
6
7
8
9
/* 
* 定义一个变量 key
*/
int key = 10;

/* 定义一个方法,实现两数相加 */
public static void add(int a, int b){
return a + b;
}

文档注释

文档注释以 /** 开始,以 */ 结束,文档注释也不支持嵌套。

1
2
3
4
5
6
7
8
9
10
11
/**
* 定义一个变量 key
*/
int key = 10;

/**
* 定义一个方法,实现两数相加
*/
public static void add(int a, int b){
return a + b;
}

Java 关键字与标识符

关键字

关键字概念:
关键字是指在程序中,Java 已经定义好的单词,具有特殊含义。

关键字举例: 在入门案例中,出现的关键字有 publicstaticvoidclass 等,这些单词已经被 Java 提前定义好了,全部都是小写字母,在 notepad++ 中有特殊的颜色 。关键字比较多,不用死记硬背,学到哪里记到哪里即可。需要一次性了解的请自行百度。

标识符

标识符: 是指在程序中,我们自己定义内容。比如 类的名字方法的名字变量的名字 等等,都是标识符。在入门案例中,出现的标识符有类的名字: HelloWorld

命名规则【硬性要求】:
1、标识符可以包含英文字母 26 个(区分大小写)、0-9 数字、$(美元符号)和 _(下划线)。 2、标识符不能以数字开头。 3、标识符不能是关键字。
命名规范【软性建议】:
1、类名规范:首字母大写,后面每个单词首字母大写(大驼峰式)。 2、方法名规范:首字母小写,后面每个单词首字母大写(小驼峰式)。 3、变量名规范:小驼峰式。用 final 修饰的变量全部大写,多个单词用 "_" 分隔。

Java 中的常量和变量

常量概述及分类

常量概念: 常量是 “不改变的量” ,在计算机程序运行时,不会被程序修改的量,即固定不变的数据。以下是常量的分类:

类型 含有 举例
整数常量 所有的整数 0,1,567,-9
小数常量 所有的小数 0.0,-0.1,2.55
字符常量 单引号引起来,只能写一个字符,必须有内容 ‘a’,’好’
字符串常量 双引号引起来,可以写多个字符,也可以不写 “A”,”Hello”,”你好”
布尔常量 只有两个值(流程控制中讲解) true,false
空常量 只有一个值(引用数据类型中讲解) null

常量练习

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
public class Constant {
public static void main(String[] args) {
// 常量的概念:在程序运行期间,固定不变的量。
// 1、字符串常量
System.out.println("ABC");
System.out.println("");
System.out.println("XYZ");

// 2、整数常量
System.out.println(30);
System.out.println(-500);

// 3、浮点数/小数常量
System.out.println(3.14);
System.out.println(-2.5);

// 4、字符常量
System.out.println('A');
System.out.println('6');
System.out.println(' '); // 代表空格字符
/*System.out.println(''); // 两个单引号中间必须有且仅有一个字符,没有不行。
System.out.println('AB'); // 两个单引号中间必须有且仅有一个字符,有两个不行。*/

// 5、布尔常量:只有两种取值。true、false。
System.out.println(true);
System.out.println(false);

// 6、空常量:null。代表没有任何数据。空常量不能直接用来打印输出。
// System.out.println(null);
}
}

变量概述及定义

变量概念: 常量是固定不变的数据,那么在程序中可以变化的量称为 变量 。在数学中,可以使用字母代替数字运算,例如 x = 1 + 5 或者 6 = x + 5。同样,在程序中,也可以用字母保存数字的方式来进行运算,提高计算能力。比如用 x 保存 5,且 x 也可以保存 6,这样 x 保存的数据是可以改变的,也就是我们所讲的变量。Java 中要求 一个变量每次只能保存一个数据 ,必须要明确保存的数据类型。所以下一章节我们去了解一下 Java 中的数据类型。

变量的定义:
1、三要素:数据类型、变量名、数据值。 2、格式为:数据类型 变量名 = 数据值;

变量练习

定义所有基本数据类型的变量,代码如下:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public class Variable {
public static void main(String[] args) {
// 变量概念:程序运行期间,内容可以发生改变的量。
int num1;
num1 = 10;
System.out.println("num1 = " + num1);
num1 = 20;
System.out.println("num1 = " +num1);

int num2 = 25;
System.out.println("num2 = " +num2);
num2 = 35;
System.out.println("num2 = " +num2);
System.out.println("===============");

// 注意:右侧数值的范围不能超过左侧数据类型的取值范围
// byte num4 = 400; // 右侧超出了 byte 数据范围,错误!
byte num3 = 30;
System.out.println("num3 = " + num3);

short num5 = 50;
System.out.println("num5 = " + num5);

long num6 = 3000000000L;
System.out.println("num6 = " + num6);

float num7 = 2.5F;
System.out.println("num7 = " + num7);

double num8 = 1.2;
System.out.println("num8 = " + num8);

char zifu1 = 'A';
System.out.println("zifu1 = " + zifu1);

// char 可以存储中文
zifu1 = '中';
System.out.println("zifu1 = " + zifu1);

// char 的范围是 0 --> 65535
zifu1 = 100;
System.out.println(zifu1);

boolean var1 = true;
System.out.println("var1 = " + var1);

var1 = false;
System.out.println("var1 = " + var1);

boolean var2 = var1;
System.out.println("var2 = " + var2);
}
}

温馨小提示:
1、long 类型: 建议数据后加 大写 L 表示,不建议用小写,易混淆。
2、float 类型: 建议数据后加 大写 F 表示,不建议用小写,易混淆。
3、整数默认为 int 类型。
4、小数默认为 double 类型。

变量的注意事项

变量的注意事项:
1、变量名称:在同一个大括号范围内,变量的名字不可以相同。 2、变量赋值:定义的变量,不赋值不能使用。

变量的注意事项 相关代码如下:

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
public static void main(String[] args) {
/*int num1 = 10; // 创建了一个新的变量,名叫 num1
int num1 = 20; // 又创建了另一个新的变量,名字也叫 num1,错误!*/

/*int num4; // 定义了一个变量,但是没有进行赋值
System.out.println(num4); // 直接使用打印输出就是错误的!
System.out.println(num5); // 在创建 num5 这变量之前,不能使用这个变量*/
int num5 = 500;
System.out.println(num5);
{
int num6 = 60;
System.out.println(num6);
}
//System.out.println(num6); // 已经超出了大括号的范围,超出了作用域,变量不能再使用了

// 同时创建了三个全都是 int 类型的变量
int a, b, c;
a = 10;
b = 20;
c = 30;
System.out.println("a = " + a + "\tb = " + b + "\tc = " + c);

// 同时创建三个 int 变量,并且同时各自赋值
int x = 100, y = 200, z = 300;
System.out.println("x = " + x + "\ty = " + y + "\tz = " + z);
}

数据类型和运算符

数据类型分类

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 个字节 1.4013E-45~3.4028E+38
双精度浮点数 double(默认) 8 个字节 4.9E-324~1.7977E+308
字符型 char 2 个字节 0-65535
布尔类型 boolean 1 个字节(有争议) true,false

我们使用代码把上面表格的内容显示出来:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public static void main(String[] args) {
// byte
System.out.println("************************************************\n");
System.out.println("基本类型:byte\t二进制位数:" + "|"+Byte.SIZE+"|");
System.out.println("包装类:java.lang.Byte");
System.out.println("最小值:Byte.MIN_VALUE=" + Byte.MIN_VALUE);
System.out.println("最大值:Byte.MAX_VALUE=" + Byte.MAX_VALUE);
System.out.println();

// char
System.out.println("************************************************\n");
System.out.println("基本类型:char\t二进制位数:" + "|"+Character.SIZE+"|");
System.out.println("包装类:java.lang.Character");
// 以数值形式而不是字符形式将Character.MIN_VALUE输出到控制台
System.out.println("最小值:Character.MIN_VALUE="+(int)Character.MIN_VALUE);
// 以数值形式而不是字符形式将Character.MAX_VALUE输出到控制台
System.out.println("最大值:Character.MAX_VALUE="+(int)Character.MAX_VALUE);
System.out.println();

// short
System.out.println("************************************************\n");
System.out.println("基本类型:short\t二进制位数:" + "|"+Short.SIZE+"|");
System.out.println("包装类:java.lang.Short");
System.out.println("最小值:Short.MIN_VALUE=" + Short.MIN_VALUE);
System.out.println("最大值:Short.MAX_VALUE=" + Short.MAX_VALUE);
System.out.println();

// int
System.out.println("************************************************\n");
System.out.println("基本类型:int\t二进制位数:" + "|"+Integer.SIZE+"|");

System.out.println("包装类:java.lang.Integer");
System.out.println("最小值:Integer.MIN_VALUE=" + Integer.MIN_VALUE);
System.out.println("最大值:Integer.MAX_VALUE=" + Integer.MAX_VALUE);
System.out.println();

// float
System.out.println("************************************************\n");
System.out.println("基本类型:float\t二进制位数:" + "|"+Float.SIZE+"|");
System.out.println("包装类:java.lang.Float");
System.out.println("最小值:Float.MIN_VALUE=" + Float.MIN_VALUE);
System.out.println("最大值:Float.MAX_VALUE=" + Float.MAX_VALUE);
System.out.println();

// long
System.out.println("************************************************\n");
System.out.println("基本类型:long\t二进制位数:" + "|"+Long.SIZE+"|");
System.out.println("包装类:java.lang.Long");
System.out.println("最小值:Long.MIN_VALUE=" + Long.MIN_VALUE);
System.out.println("最大值:Long.MAX_VALUE=" + Long.MAX_VALUE);
System.out.println();

// double
System.out.println("************************************************\n");
System.out.println("基本类型:double\t二进制位数:" + "|"+Double.SIZE+"|");
System.out.println("包装类:java.lang.Double");
System.out.println("最小值:Double.MIN_VALUE=" + Double.MIN_VALUE);
System.out.println("最大值:Double.MAX_VALUE=" + Double.MAX_VALUE);
System.out.println();
System.out.println("************************************************");
}

Java 中的默认类型: 整数类型是 int , 浮点类型是 double 。
Java 引用数据类型: 这部分后面会涉及到,请往下阅读。

数据类型转换

Java 程序中要求参与计算的数据,必须要保证数据类型的一致性,如果数据类型不一致将发生 类型转换异常

自动类型转换

概念: 将取值范围小的类型自动提升为取值范围大的类型。
转换规则: 范围小的类型向范围大的类型提升,byte、short、char ‐‐> int ‐‐> long ‐‐> float ‐‐> double 。

自动类型转换 代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class DataTypeConversion {
public static void main(String[] args) {
// 数据类型转换之隐式转换
// 1、特点:代码不需要进行特殊处理,自动完成。
// 2、规则:数据范围从小到大。
int x1 = 3;
byte b1 = 4; // byte 取值范围:-128~127
x1 = x1 + b1; // 这里的 b1 自动转换为 int
System.out.println(x1);
double num2 = 2.5F;
System.out.println(num2);

// 左边是float类型,右边是long类型,long --> float,范围是float更大一些,符合从小到大的规则,发生自动类型转换
float num3 = 30L;
System.out.println(num3);
}
}

以下是一道 面试题 ,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main(String[] args) {
// 面试题:以下程序是否有问题,给出理由。
byte b01 = 3;
byte b02 = 4;

System.out.println(b01);
System.out.println(b02);

byte b03 = b01 + b02;
System.out.println(b03);

byte b04 = 3 + 4; // java 编译器有常量优化机制
System.out.println(b04);

// 问题解析:
// 1、byte 与 byte (或short,char)进行运算的时候会自动提升为 int ,两个 int 类型相加的结果也是 int 类型
// 2、b01 和 b02 是两个变量,变量存储的值是变化,在编译的时候无法判断里面具体的值,相加有可能会超出 byte 的取值范围
// 3、程序是有错的,自己拿到 IDEA 上就知道了。
}

下面是有关 ASCll 码表 中字符与数字对应关系,例如 字符 0 对应 ASCll 码表中的 数字 48

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class DataTypeChar {
public static void main(String[] args) {
// 数字和字符的对照关系表(编码表):
// ASCII 码表:American Standard Code for Information Interchange,美国信息交换标准代码。
// Unicode 码表:万国码。也是数字和符号的对照关系,开头0-127部分和ASCII完全一样,但是从128开始包含有更多字符。
// 48 - '0'
// 65 - 'A'
// 97 - 'a'

char zifu1 = '1';
System.out.println(zifu1 + 0); // 49

char zifu2 = 'A'; // 其实底层保存的是65数字
System.out.println(zifu2 + 0); // 65

char zifu3 = 'c';
// 左侧是int类型,右边是char类型, char --> int,确实是从小到大,从而发生了自动类型转换
int num = zifu3;
System.out.println(num); // 99

char zifu4 = '中';
System.out.println(zifu4 + 0); // 20013
}
}

强制类型转换

强制类型转换 就是将 取值范围大的类型强制转换成取值范围小的类型 。比较而言,自动转换是 Java 自动执行的,而强制转换需要我们自己手动执行。强制类型转换格式: 数据类型 变量名 =(数据类型)被转数据值; 代码演示如下:

1
2
3
4
5
6
7
8
9
10
public static void main(String[]args){
//short类型变量,内存中2个字节
short s = 1;

// 将会出现编译失败,s 和 1 做运算的时候,1 是 int 类型,s 会被提升为 int 类型
// s+1后的结果是int类型,将结果在赋值会short类型时发生错误short内存2个字节,int类型4个字节
// 必须将 int 强制转成 short 才能完成赋值
s = s + 1; //编译失败
s = (short)( s + 1 ); //编译成功
}

强制类型转换 的图解如下:

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
public static void main(String[]args){
// 数据类型转换之强制转换
// 1. 特点:代码需要进行特殊的格式处理,不能自动完成。
// 2. 格式:范围小的类型 范围小的变量名 = (范围小的类型) 原本范围大的数据;
// 注意事项:
// 1. 强制类型转换一般不推荐使用,因为有可能发生精度损失、数据溢出。
// 2. byte/short/char这三种类型都可以发生数学运算,例如加法“+”.
// 3. byte/short/char这三种类型在运算的时候,都会被首先提升成为int类型,然后再计算。
// 4. boolean类型不能发生数据类型转换
int x2 = 3;
byte b2 = 4;
b2 = (byte)(x2 + b2); //b2=(byte)x2+b2;这种写法是会出错的
System.out.println(b2);

//00000000 00000000 00000000 10000010 130的二进制
//10000010 -126补码
//00000001 -1求反码
//10000001 -126反码
//11111110 -126原码
byte b3 = (byte)(126 + 4);
System.out.println(b3);

//00000000 00000000 00000001 00101100 300的二进制
//00101100 正数的原码反码和补码一样
byte b4 = (byte)300;
System.out.println(b4);

System.out.println((char)('a' + 1)); //结果是b
System.out.println("hello"+'a'+1); //任何数据类型用+与字符串相连接都会产生新的字符串
System.out.println('a'+1+"hello"); //98hello,因为有ASCII码表,a字符对应的是int类型的97
}

小提示:

1. 浮点转成整数,直接取消小数点,可能造成数据损失精度。
2. int 强制转成 short 砍掉2个字节,可能造成数据丢失。

各种运算符

算术运算符

算术运算符包括 中文解释
+ 加法运算,字符串连接运算
- 减法运算
* 乘法运算
/ 除法运算
% 取模运算,两个数字相除取余数
++,- - 自增自减运算(单独说)

算术运算符 代码演示如下:

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
/**
* 1. 运算符:进行特定操作的符号。例如:+
* 2. 表达式:用运算符连起来的式子叫做表达式。例如:20 + 5。又例如:a + b
* 3. 四则运算 ==> 加:+ 减:- 乘:* 除:/
* 4. 取模运算(取余数):% ,只有对于整数的除法来说,取模运算符才有余数的意义。
* 5. 首先计算得到表达式的结果,然后再打印输出这个结果
* 6. 复习一下除法公式:被除数 / 除数 = 商 ... 余数
* 7. 对于一个整数的表达式来说,除法用的是整除,整数除以整数,结果仍然是整数。只看商,不看余数。
* 8. 注意事项:一旦运算当中有不同类型的数据,那么结果将会是数据类型范围大的那种。
*/
public class Operator {
public static void main(String[] args) {
// 两个常量之间可以进行数学运算
System.out.println(20 + 30);

// 两个变量之间也可以进行数学运算
int a = 20;
int b = 30;
System.out.println(a - b); // -10

// 变量和常量之间可以混合使用
System.out.println(a * 10); // 200

int x = 10;
int y = 3;

int result1 = x / y;
System.out.println(result1); // 3

int result2 = x % y;
System.out.println(result2); // 余数【模】为 1

// int + double --> double + double --> double
double result3 = x + 2.5;
System.out.println(result3); // 12.5
}
}

取模运算 比较特殊,具体的解释代码里都有,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Operator{
public static void main(String[] args){
// % --> 取模运算符
// % 运算符结果的符号只和左边有关系,与右边无关
// 任何一个正整数 %2 结果不是 0 就是 1 , 可以用来当作切换条件

System.out.println(10 / 3); // 整数相除结果只能是整数
System.out.println(10 / 3.0); // 如果想得到小数,把其中一个数变成小数,另一个数在运算的时候会自动类型提升
System.out.println(-6 % 5);
System.out.println(13 % -5);
}
}

// 输出结果:
3
3.3333333333333335
-1
3

赋值运算符

赋值运算符包括 中文解释
= 等于号
+= 加等于
-= 减等于
*= 乘等于
/= 除等于
%= 取模等

赋值运算符 代码演示如下:

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
public class Operator{
public static void main(String[] args){
// 赋值运算符 =
int a1 = 3; // 把右边的常量值赋值给左边的变量,左边必须是变量

// 赋值运算符 +=
a1 += 4; // a1 = a1 + 4;
System.out.println(a1);

// 赋值运算符 -=
a1 -= 5; // a1 = a1 - 4;
System.out.println(a1);

// 赋值运算符 *=
a1 *= 2; // a1 = a1 * 4;
System.out.println(a1);

// 赋值运算符 /=
a1 /= 2; // a1 = a1 / 4;
System.out.println(a1);

// 赋值运算符 %=
a1 %= 2; // a1 = a1 % 4;
System.out.println(a1);
}
}

比较运算符

比较运算符包括 中文解释
== 比较符号两边数据是否相等,相等结果是true。
!= 不等于符号,如果符号两边的数据不相等,结果是true。
> 比较符号左边的数据是否大于右边的数据,如果大于结果是true。
>= 比较符号左边的数据是否大于或等于右边的数据,如果大于等于结果是true。
< 比较符号左边的数据是否小于右边的数据,如果小于结果是true。
<= 比较符号左边的数据是否小于或等于右边的数据,如果小于等于结果是true。

比较运算符 代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
public class Operator{
public static void main(String[] args){
// 比较运算符,也称为关系运算符
// == , != , > , >= , < , <=
System.out.println(4 == 3);
System.out.println(4 != 3);
System.out.println(4 > 4);
System.out.println(4 >= 4);
System.out.println(4 < 3);
System.out.println(4 <= 3);
}
}

逻辑运算符

逻辑运算符包括: 相关说明

&& 短路与
两边都是 true,结果是 true
一边是 false,结果是 false
短路特点: 符号左边是 false,右边不再运算

|| 短路或
两边都是 false,结果是 false
一边是 true,结果是 true
短路特点: 符号左边是 true,右边不再运算

! 取反
!true 结果是 false
!false 结果是 true

逻辑运算符 是用来连接两个布尔类型结果的运算符,运算结果都是布尔值 true 或者 false 。代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String[] args) {
// 逻辑运算符(不支持短路运算) & | ^(异或)
// 逻辑运算符(支持短路运算) && || !
int a = 10;
int b = 23;
int c = 34;
System.out.println("&\t" + (a > b & b < c)); // false,a > b 和 b < c 都会执行
System.out.println("&&\t" + (a > b && b < c)); // false, 当 a > b 被判断为错误时,b < c 不执行
System.out.println("|\t" + (a > b | b < c)); // true
System.out.println("||\t" + (a > b || b < c)); // true
System.out.println("^\t" + (a > b ^ b < c)); // 相同为 false,不相同为 true 。例如:1^1=0 0^0=0 1^0=1 0^1=1
System.out.println("!\t" + !(a < b));
}

位运算符

位运算符 主要针对二进制,它包括了:& 与| 或~ 非^ 异或<< 左移>> 右移 。从表面上看,位运算符 似乎有点像逻辑运算符,但逻辑运算符是针对两个关系运算符来进行逻辑运算,而位运算符主要针对两个二进制数的位进行逻辑运算 。下面详细介绍每个位运算符。相关代码演示如下:

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
public static void main(String[] args) {
// 位运算符 & ^ | ~(按位取反)
// ^ 的特点:一个数据对另一个数据位异或两次,该数本身不变。
System.out.println("^ = " + (5 ^ 10 ^ 10)); // 可利用此特点不通过第三者而达到交换两个数的目的
System.out.println("6 & 2 = " + (6 & 2));
System.out.println("6 ^ 2 = " + (6 ^ 2));
System.out.println("6 | 2 = " + (6 | 2));
System.out.println("~56 = " + (~56));

// 位运算符:左移 << 左移几位就乘以 2 的几次方
System.out.println("12左移3位:\t" + (12 << 3));
System.out.println("12左移5位:\t" + (12 << 5));

// 位运算符:右移 >> 右移几位就除以 2 的几次幂
System.out.println("16右移3位:\t" + (16 >> 3));
System.out.println("128右移5位:\t" + (128 >> 5));
}

// 输出结果:
6 | 2 = 6
~56 = -57
12左移3位: 96
12左移5位: 384
16右移3位: 2
128右移5位: 4

三元运算符

三目运算符 又称 条件运算符 ,是计算机语言(c,c++,java等)的重要组成部分。它是 唯一一个有 3 个操作数 的运算符,有时又被称为 三元运算符 。一般来说,三目运算符的结合性是右结合的。【————百度百科】

三元运算符格式: 数据类型变量名 = 布尔类型表达式 ? 结果1 : 结果2

三元运算符计算方式: 如果 布尔类型表达式 结果是 true,三元运算符整体结果为 结果1,然后把 结果1 赋值给变量。否则就把 结果2 赋值给变量。代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[]args){
int i = (1 == 2 ? 100 : 200);
System.out.println(i); // 200

int j = (3 <= 4 ? 500 : 600);
System.out.println(j); // 500

int max = getMax(31,32,33);
System.out.println(max);
}

// 求三个整数中的最大值
public static int getMax(int a , int b , int c ){
return (a > b ? a : b) > c ? (a > b ? a : b) : c;
}

自增自减运算符

自增自减运算符 的所有知识点都在下面的代码演示中,所以这里就不做过多的介绍,代码演示如下:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
* 自增运算符:++ 自减运算符:--
* 1. 基本含义:让一个变量涨一个数字1,或者让一个变量降一个数字1
* 2. 使用格式:写在变量名称之前,或者写在变量名称之后。例如:++num ,也可以 num++
* 3. 使用方式:
* 1. 单独使用:不和其他任何操作混合,自己独立成为一个步骤。
* 2. 混合使用:和其他操作混合,例如与赋值混合,或者与打印操作混合,等。
* 4. 使用区别:
* 1. 在单独使用的时候,前++和后++没有任何区别。也就是:++num;和num++;是完全一样的。
* 2. 在混合的时候,有【重大区别】
* A. 如果是【前++】,那么变量【立刻马上+1】,然后拿着结果进行使用。 【先加后用】
* B. 如果是【后++】,那么首先使用变量本来的数值,【然后再让变量+1】。 【先用后加】
* 5. 注意事项:只有变量才能使用自增、自减运算符。常量不可发生改变,所以不能用。
*/
public static void main(String[] args) {
int num1 = 10;
System.out.println(num1); // 10
++num1; // 单独使用,前++

System.out.println(num1); // 11
num1++; // 单独使用,后++

System.out.println(num1); // 12
System.out.println("=================");

// 与打印操作混合的时候
int num2 = 20;
// 混合使用,先++,变量立刻马上变成21,然后打印结果21
System.out.println(++num2); // 21
System.out.println(num2); // 21
System.out.println("=================");

int num3 = 30;
// 混合使用,后++,首先使用变量本来的30,然后再让变量+1得到31
System.out.println(num3++); // 30
System.out.println(num3); // 31
System.out.println("=================");

int num4 = 40;
// 和赋值操作混合
int result1 = --num4; // 混合使用,前--,变量立刻马上-1变成39,然后将结果39交给result1变量
System.out.println(result1); // 39
System.out.println(num4); // 39
System.out.println("=================");

int num5 = 50;
// 混合使用,后--,首先把本来的数字50交给result2,然后我自己再-1变成49
int result2 = num5--;
System.out.println(result2); // 50
System.out.println(num5); // 49
System.out.println("=================");

int x = 10;
int y = 20;
// 11 + 20 = 31
int result3 = ++x + y--;
System.out.println(result3); // 31
System.out.println(x); // 11
System.out.println(y); // 19

// 30++; // 错误写法!常量不可以使用++或者--
}

JShell 脚本工具

JShellJDK9 的新特性,这部分是个了解内容,需了解请参考: JShell 工具

流程控制语句

流程控制概述

在一个程序执行的过程中,各条语句的执行顺序 对程序的结果是有直接影响的。也就是说,程序的流程对运行结果有直接的影响。所以,我们必须清楚每条语句的执行流程。而且,很多时候我们要通过控制语句的执行顺序来实现我们要完成的功能。接下来介绍 三种流程控制结构

顺序结构

顺序结构 就是 从上到下依此执行 ,代码演示如下:

1
2
3
4
5
6
7
public static void main(String[] args){
// 顺序执行,根据编写的顺序,从上到下运行
System.out.println("今天天气不错");
System.out.println("挺风和日丽的");
System.out.println("我们下午没课");
System.out.println("这的确挺爽的");
}

选择结构

选择结构两种形式: if 选择结构switch 选择结构 。接下来我们详细讲一下这两种选择结构的 异同点

选择结构-if

第一种格式:if
if (关系表达式) {     语句体; }
第一种格式执行流程:
1、首先判断关系表达式,看其结果是 true 还是 false 2、如果是 true 就执行语句体;如果是 false 就不执行语句体 3、代码举例如下
1
2
3
4
5
6
// 因为 8 比 3 更大,所以输出结果为 OK!
public static void main(String[] args){
if(8 > 3){
System.out.println("OK!");
}
}
第二种格式:if…else
if (关系表达式) {     语句体1; } else {     语句体2; }
第二种格式执行流程:
1、首先判断关系表达式,看其结果是 true 还是 false 2、如果是 true 就执行语句体1;如果是 false 就执行语句体2 3、代码举例如下
1
2
3
4
5
6
7
8
// 因为 8 比 10 更小,所以输出结果为 NO!
public static void main(String[] args){
if(8 > 10){
System.out.println("OK!");
} else {
System.out.println("NO!");
}
}
第三种格式:if…else if…else
if (关系表达式1) {     语句体1; } else if (关系表达式2) {     语句体2; }... }else if(关系表达式n) {     语句体n; } else {     语句体n+1; }
第三种格式执行流程:
1、首先判断关系表达式1,看其结果是 true 还是 false 2、如果是 true 就执行语句体1;如果是 false 就继续判断关系表达式2,看其结果是 true 还是 false 3、如果关系表达式2是 true ,就执行语句体2 ,如果是 false 就继续判断关系表达式3,看其结果是 true 还是 false 4、…… 5、如果没有任何关系表达式为 true,就执行语句体n+1 6、案例演示如下

综合案例: 学生成绩等级设计 ,指定考试成绩,判断学生等级。

评分机制如下:
优秀:90~100 很好:80~89 良好:70~79 及格:60~69 加油: 0~60
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
public static void main(String[] args){

Scanner scanner = new Scanner(System.in);

while (true) {

System.out.print("请输入一个整数:");
int score = scanner.nextInt();

if (score < 0 || score > 100) {
System.out.println("你的成绩是错误的");
} else if (score >= 90 && score <= 100) {
System.out.println("你的成绩属于优秀");
} else if (score >= 80 && score < 90) {
System.out.println("你的成绩属于很好");
} else if (score >= 70 && score < 80) {
System.out.println("你的成绩属于良好");
} else if (score >= 60 && score < 70) {
System.out.println("你的成绩属于及格");
} else {
System.out.println("你的成绩属于需要再接再厉!");
}

}
}

选择结构-switch

switch 语法格式:
switch (表达式) {     case 常量值1:         语句体1;         break;     case 常量值2:         语句体2;         break;     ...     default:         语句体n+1;         break; }

switch 语句执行流程: 首先 获取到表达式的值,然后 把这个值和 case 的常量值依次比较,一旦有对应的值,就会执行相应 case 的语句体。在执行的过程中,遇到 break 就会结束。最后 ,如果所有的 case 都和表达式的值不匹配,就会执行default 语句体 部分,然后程序结束。代码演示如下:

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
public static void main(String[] args) {

// 定义变量,判断是星期几
int weekday = 6;

// switch 语句实现选择
switch(weekday) {
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;
}

}

小提示:

switch 语句中 ,表达式的数据类型,可以是 byte,short,int,char,enum(枚举)JDK7 后可以接收 字符串

case 的穿透性: 在 switch 语句中,如果 case 的后面不写 break ,将出现 穿透现象 ,也就是不会再判断下一个 case 的值,而是直接向后运行,直到遇到 break,或者整体 switch 结束。代码举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[]args){
int i = 5;
switch(i){
case 0:
System.out.println("执行case0");break;
case 5:
System.out.println("执行case5");
case 10:
System.out.println("执行case10");
default:
System.out.println("执行default");
}
}

// 输出结果
执行case5
执行case10
执行default

在上述程序中,执行 case5 后,由于没有 break 语句,程序会一直向后走 ,不会再判断 case,直接运行完整体 switch 或者遇到 break 才会结束。由于 case 存在穿透性,因此初学者在编写 switch 语句时,必须要写上 break 。

循环结构

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

循环结构-for

for 循环的格式:
for (初始化表达式①; 布尔表达式②; 步进表达式④) {     循环体③ }
for 循环的执行流程:
1、执行顺序:①②③④ > ②③④ > ②③④ … 直到②不满足循环条件为止。 2、①负责完成循环变量初始化 3、②负责判断是否满足循环条件,不满足则跳出循环 4、③是具体执行的语句 5、④表示循环后,循环条件所涉及变量的变化情况

代码演示如下:

1
2
3
4
5
6
public static void main(String[] args){
// 循环 10 次,输出 HelloWorld 10次。定义变量从 0 开始,循环条件为 x < 10
for (int x = 0; x < 10; x++) {
System.out.println("HelloWorld" + x);
}
}

一个小案例: 使用循环,计算 1-100 之间的偶数和 。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args){
// 1、定义一个初始化变量,记录累加求和,初始值为 0
int sum = 0;

// 2、利用 for 循环获取 1‐100 之间的数字
for (int i = 1; i <= 100; i++) {
// 3、判断获取的数组是奇数还是偶数
if(i % 2 == 0){
// 4、如果是偶数就累加求和
sum += i;
}
}

// 5、循环结束之后,打印累加结果
System.out.println("sum: " + sum);
}

循环结构-foreach

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
public static void main(String[] args) {

int[] num = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i : num) // 这就是 for 的增强,类似于自然语言 for each
System.out.println(i);


int[] numbers = {10, 20, 30, 40, 50};
for (int x : numbers) {
System.out.print(x);
System.out.print(",");
}
System.out.print("\n");


String[] names = {"James", "Larry", "Tom", "Lacy", "Bob", "Jobs"};
for (String name : names) {
if (name == "Larry")
continue; // 结束本次循环,开始下一次循环
if (name == "Lacy")
break; // 结束所有循环,直接跳出
System.out.print(name);
System.out.print(",");
}
System.out.println("\n-----------------------------");


for (int x = 10; x < 20; x = x + 1) {
System.out.print("value of x : " + x);
System.out.print("\n");
}

}

循环结构-while

while 循环的格式:
初始化表达式① while (布尔表达式②) {     循环体③     步进表达式④ }
while 循环的执行流程:
1、执行顺序:①②③④ > ②③④ > ②③④ … 直到②不满足循环条件为止。 2、①负责完成循环变量初始化 3、②负责判断是否满足循环条件,不满足则跳出循环 4、③是具体执行的语句 5、④表示循环后,循环变量的变化情况

代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
// while 循环实现打印 10次 HelloWorld
public static void main(String[] args){
// 定义初始化变量
int i = 1;

// 循环条件 i <= 10
while(i <= 10){
System.out.println("HelloWorld");
// 步进表达式
i++;
}
}

一个小案例: 使用循环,计算 1-100 之间的和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main(String[] args){
// 使用 while 循环实现
// 定义一个变量,记录累加求和
int sum = 0;

// 定义初始化表达式
int i = 1;

// 使用 while 循环让初始化表达式的值变化
while(i <= 100){
// 累加求和
sum += i;
// 步进表达式改变变量的值
i++;
}

// 循环结束之后,打印累加结果
System.out.println("1‐100 的和是:" + sum);
}

循环结构-do…while

do…while 循环的格式:
初始化表达式① do {     循环体③     步进表达式④ } while(布尔表达式②);
do…while 循环的执行流程:
1、执行顺序:①②③④ > ②③④ > ②③④ … 直到②不满足循环条件为止。 2、①负责完成循环变量初始化 3、②负责判断是否满足循环条件,不满足则跳出循环 4、③是具体执行的语句 5、④表示循环后,循环变量的变化情况

代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
// while 循环实现打印 10 次 HelloWorld
public static void main(String[] args){
// 定义初始化变量
int i = 1;

// 循环条件 i <= 10
do {
System.out.println("HelloWorld");
// 步进表达式
i++;
} while(i <= 10);
}

注意: do…while 循环中的 while 后面有分号哦,可不要忘记了。

do…while 循环的特点: 无条件执行一次循环体,即使我们将循环条件直接写成 false ,也依然会循环一次。这样的循环具有一定的风险性,因此不太建议使用 do…while 循环,推荐使用 for 循环和 while 循环

1
2
3
4
5
public static void main(String[] args){
do {
System.out.println("无条件执行一次");
} while(false);
}

接下来演示一个 do…while 版的 9 * 9 乘法口诀表 小案例,代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
int i = 1; //外循环变量定义在外面
do {

int j = 1; // 内循环变量定义在第一个 do…while 里面

do {
System.out.printf("%d * %d = %d\t", i, j, i * j);
j++;
} while (j <= i);

System.out.println();
i++;

} while (i <= 9);
}

扩展知识点

break 和 continue

  • break 使用场景: 跳出循环,只能在 switch循环语句 中使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public static void main(String[] args){
    for (int i = 1; i <= 10; i++) {
    // 打印完两次 HelloWorld 就结束循环
    if(i == 3){
    break;
    }
    System.out.println("HelloWorld" + i);
    }
    }
  • continue 使用场景: 结束本次循环,继续下一次的循环。只能在 循环语句 中使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public static void main(String[] args){
    for(int i = 1;i <= 10;i++){
    // 不打印第三次 HelloWorld
    if(i == 3){
    continue;
    }
    System.out.println("HelloWorld" + i);
    }
    }

死循环

死循环: 也就是循环中的条件永远为 true ,死循环是永不结束的循环 。例如:while(true){} 。在后期的开发中,会出现使用死循环的场景。例如:我们需要读取用户输入的输入,但是用户输入多少数据我们并不清楚,也只能使用死循环,当用户不想输入数据了,就可以结束循环了,如何去结束一个死循环呢,就需要使用到跳出语句了。代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 以下是三种循环的死循环
public static void main(String[] args) {

// 以下是 for 的死循环,去掉 break 就是死循环
for ( ; ; ) {
System.out.println("I LOVE YOU!");
break;
}


// 以下是 do~while 的死循环,去掉 break 就是死循环
do {
System.out.println("HOPE IS BEAUTIFUL!");
break;
} while(true);


// 以下是 while 的死循环
while (true) {
System.out.println("SHAPE OF YOU!");
}

}

嵌套循环

嵌套循环 是指一个循环的循环体是另一个循环。比如 for 循环里面还有一个 for 循环 ,就是 嵌套循环 。当然也可以嵌套多层,而且不同的循环结构相互之间也可以嵌套。循环次数: 总共的循环次数 = 外循环次数 * 内循环次数

嵌套循环格式举例:
for (初始化表达式①; 循环条件②; 步进表达式⑦) {     for (初始化表达式③; 循环条件④; 步进表达式⑥) {         执行语句⑤;     } }
嵌套循环执行流程:
1、执行顺序:①②③④⑤⑥ > ④⑤⑥ > ⑦②③④⑤⑥ > ④⑤⑥ 2、外循环一次,内循环多次。比如跳绳:一共跳5组,每组跳10个。5组就是外循环,10个就是内循环。

嵌套循环练习: 使用嵌套循环,打印 5*8 的矩形 。实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
// 5*8 的矩形,打印5行*号,每行8个
public static void main(String[] args){
// 外循环 5 次,内循环 8 次
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 8; j++) {
// 不换行打印星号
System.out.print("*");
}
// 内循环打印 8 个星号后,需要一次换行
System.out.println();
}

开发工具和方法

开发工具概述

我们常用的 Java 开发工具EclipseNetBeansIDEA 等等。这里只介绍 IDEA因为是世界上用的最多的 。 IDEA 是一个专门针对 Java 的集成开发工具(IDE),由 Java 语言编写。所以需要有 JRE 运行环境并配置好环境变量 ,它可以极大地提升我们的开发效率。在公司中,使用的就是 IDEA 进行开发。具体的安装和使用请参考: IDEA 入门教程

Java 中的方法

方法的概述

在学习运算符的时候,需要为每个运算符单独地创建一个新的类。这时我们发现,这样编写代码是非常的繁琐,而且重复的代码过多。能否避免这些重复的代码呢?当然可以,使用方法来实现。方法: 在 C 语言中称之为 函数 ,就是将一个功能抽取出来,把代码单独定义在一个大括号内,形成一个单独的功能。当我们需要这个功能的时候,就可以去调用。这样即实现了代码的复用性,也解决了代码冗余的现象

方法的格式:
修饰符 返回值类型 方法名 (参数列表){     方法体     return 返回值; }
方法的格式的解释:
修饰符:目前固定写法 public static 返回值类型:基本数据类型和引用数据类型 方法名:为我们定义的方法起名,满足标识符的规范,用来调用方法。 参数列表:可以空参,也可以有参 return:方法结束。如果返回值类型是 void ,方法大括号内的 return 可以不写。其他情况一律需要返回值。

代码演示如下:

1
2
3
4
// 定义 twoSum 方法,实现两个整数相加
public static void twoSum(int a , int b){
System.out.println("两数之和为:" + (a + b));
}

方法定义的两个明确

举例说明: 定义方法实现 两个整数的求和计算 。需要明确的两件事如下:

明确返回值类型:
方法计算的是整数的求和,结果也必然是个整数,所以返回值类型定义为 int 类型。
明确参数列表:
计算哪两个整数的和,并不清楚,但可以确定是整数,参数列表可以定义两个int类型的变量,由调用者调用方法时传递

代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args){
// 调用方法 getSum,传递两个整数,这里传递的实际数据又称为实际参数
// sum 接收方法计算后的结果作为返回值
int sum = getSum(5,6);
System.out.println(sum);
}

/*定义计算两个整数和的方法,返回值类型和计算结果都是 int
参数:定义两个 int 类型参数。这两个参数称为形式参数*/
public static int getSum(int a,int b){
return a + b;
}

方法的调用

方法在定义完毕后,方法不会自己运行,必须被调用才能执行 。【方法的调用有三种方式,直接调用赋值调用输出调用 ,三种调用方式自行搜索一下,这里只是简单了解。】我们可以在 主方法 main 中来调用我们自己定义好的方法。在主方法中,直接写要调用的方法名字就可以调用了【前提是你定义的方法 必须被 static 关键字修饰 才行】。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void main(String[] args) {

// 单独调用
sum(10, 20);
System.out.println("===========");


// 打印调用
System.out.println(sum(10, 20)); // 30
System.out.println("===========");


// 赋值调用
int number = sum(15, 25);
number += 100;
System.out.println("变量的值:" + number); // 140

}

public static int sum(int a, int b) {
System.out.println("方法执行啦!");
int result = a + b;
return result;
}

方法的调用图解

方法的重载

方法重载:
1、方法重载:指在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可,与修饰符和返回值类型无关。 2、参数列表:个数不同,数据类型不同,顺序不同。 3、重载方法调用:JVM 通过方法的参数列表,调用不同的方法。

方法重载 代码演示如下:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public static void main(String[] args) {

// 普通方法
print(3, 3);

// 方法重载:方法名字相同,形式参数的类型不同或者形式参数的个数不同
// 重载: 方法名相同,参数列表不同,与返回值类型无关
// 重载的分类: 1、参数个数不同 2、参数类型不同 3、参数顺序不同
double sum1 = add(10, 20.1);
System.out.println(sum1);

int sum2 = add(10, 20, 30);
System.out.println(sum2);

double sum3 = add(12.3, 13);
System.out.println(sum3);

}


/**
* 在控制台输出矩形星形
* 1、明确返回值类型,经分析没有具体的返回值类型,那么返回值类型就是 void
* 2、明确参数列表 int a, int b
*/
public static void print(int a, int b) {
for (int i = 1; i <= a; i++) { //行数
for (int j = 1; j <= b; j++) { //列数
System.out.print("*");
}
System.out.println();
}
// 如果返回值类型是 void, return 可以省略,即使省略系统也会默认给加上, 形式是 return;
//return ;
}


/**
* 求两个整数的和
* 1、返回值类型 int
* 2、参数列表 int a, int b
*/
public static double add(int a, double b) {
return a + b;
}


/**
* 求三个整数的和
* 1、返回值类型 int
* 2、参数列表 int a,int b,int c
*/
public static int add(int a, int b, int c) {
return a + b + c;
}


/**
* 求两个小数的和
* 1、返回值类型 double
* 2、参数列表 double a, double b
*/
public static double add(double a, int b) {
return a + b;
}

方法的注意事项

方法的注意事项:
1、方法必须定义在类中方法外 2、方法不能定义在另一个方法里面 3、返回值类型必须要和语句返回的类型相同,否则编译失败

还有 更多的注意事项 写在代码的注释里面了,代码演示如下:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
* 使用方法的时候,有如下注意事项:
* 1、方法应该定义在类当中,但是不能在方法当中再定义方法。不能嵌套。
* 2、方法定义的前后顺序无所谓。
* 3、方法定义之后不会执行,如果希望执行,一定要调用。三种调用方式:单独调用、打印调用、赋值调用。
* 4、如果方法有返回值,那么必须写上“return 返回值;”,不能不写。
* 5、return 后面的返回值数据,必须和方法的返回值类型,对应起来。
* 6、对于一个 void 没有返回值的方法,不能写 return 后面的返回值,只能写 return 自己。
* 7、对于 void 方法当中最后一行的 return 可以省略不写。
* 8、一个方法当中可以有多个 return 语句,但是必须保证同时只有一个会被执行到,两个 return 不能连写。
*/
class MethodNotice {

public static int method1() {
return 10;
}


public static void method2() {
// return 10; // 错误的写法!方法没有返回值,return后面就不能写返回值。
return; // 没有返回值,只是结束方法的执行而已。
}


public static void method3() {
System.out.println("AAA");
System.out.println("BBB");
// return; // 最后一行的return可以省略不写。
}


public static int getMax(int a, int b) {
/*int max;
if (a > b) {
max = a;
} else {
max = b;
}
return max;*/

/*if (a > b) {
return a;
} else {
return b;
}*/

return a > b ? a : b;
}

}

数组知识

数组的概述和初始化

容器的概述

现在需要统计某公司员工的工资情况,例如 计算平均工资、找最高工资 等。假设该公司有 50 名员工,那么首先需要声明 50 个变量来分别记住每位员工的工资,然后再进行操作,这样做会显得很麻烦,而且错误率也会很高。因此我们可以使用 容器 进行操作。将所有的数据全部存储到一个容器中,统一操作。容器 是将多个数据存储到一起,每个数据称为该容器的 元素 。生活中常见的容器:水杯,衣柜,教室 等等。

数组的概念

数组 就是存储 数据长度固定 的容器,保证了多个数据的数据类型一致。数组的其他介绍都在代码里了,代码演示如下:

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
/**
* 01-数组的概念:数组是一种容器,可以同时存放多个数据值。
* 02-数组的特点:
* 1、数组是一种引用数据类型
* 2、数组当中的多个数据,类型必须统一
* 3、数组的长度在程序运行期间不可改变
* 03-数组的初始化:在内存当中创建一个数组,并且向其中赋予一些默认值。
* 04-两种常见的初始化方式:1. 动态初始化(指定长度) 2. 静态初始化(指定内容)
* 05-动态初始化数组的格式:数据类型[] 数组名称 = new 数据类型[数组长度];
* 06-解析含义:
* 1、左侧数据类型:也就是数组当中保存的数据,全都是统一的数据类型
* 2、左侧的中括号:代表是一个数组
* 3、左侧数组名称:给数组取一个名字
* 4、右侧的 new:代表创建数组的动作
* 5、右侧数据类型:必须和左边的数据类型保持一致
* 6、右侧中括号的长度:也就是数组当中,到底可以保存多少个数据,是一个 int 类型的值
*/
public static void main(String[] args) {

// 创建一个 int 类型的数组,里面可以存放 300 个 int 数据。 格式:数据类型[] 数组名称 = new 数据类型[数组长度];
int[] arrayA = new int[300];

// 创建一个 double 类型的数组,能存放 10 个 double 类型的数据
double[] arrayB = new double[10];

// 创建一个 String 类型的数组,能存放 5 个字符串
String[] arrayC = new String[5];

}

数组的初始化

接下来介绍 数组的初始化和注意事项 ,都写在代码里了,请看代码:

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
/**
* 01-动态初始化(指定长度):在创建数组的时候,直接指定数组当中的数据元素个数。
* 02-静态初始化(指定内容):在创建数组的时候,不直接指定数据个数多少,而是直接将具体的数据内容进行指定。
* 03-静态初始化标准格式:数据类型[] 数组名称 = new 数据类型[] { 元素1, 元素2, ... };
* 04-使用静态初始化数组的时候,格式还可以省略。省略格式:数据类型[] 数组名称 = { 元素1, 元素2, ... };
* 05-注意事项:
* 1、静态初始化没有直接指定长度,但是根据大括号里面的元素具体内容,也可以自动推算出来长度。
* 2、静态初始化标准格式可以拆分成为两个步骤。
* 3、动态初始化也可以拆分成为两个步骤。
* 4、静态初始化一旦使用省略格式,就不能拆分成为两个步骤了。
* 06-使用建议:如果不确定数组当中的具体内容,用动态初始化;否则,已经确定了具体的内容,用静态初始化。
*/
public static void main(String[] args) {

// 直接创建一个数组,里面装的全都是 int 数字,具体为:5、15、25
int[] arrayA = new int[]{5, 15, 25, 40};

// 创建一个数组,用来装字符串:"Hello"、"World"、"Java"
String[] arrayB = new String[]{"Hello", "World", "Java"};

// 省略格式的静态初始化
int[] arrayC = {10, 20, 30};

// 静态初始化的标准格式,可以拆分成为两个步骤
int[] arrayD;
arrayD = new int[]{11, 21, 31};

// 动态初始化也可以拆分成为两个步骤
int[] arrayE;
arrayE = new int[5];

// 静态初始化的省略格式,不能拆分成为两个步骤。
// int[] arrayD;
// arrayD = { 10, 20, 30 };

}

数组的访问

数组索引: 每一个存储到数组的元素,都会自动的拥有一个 编号,从 0 开始 ,这个自动编号称为 数组索引(index) 。我们可以通过 数组的索引 访问到 数组中的元素访问格式: 数组名[索引] ,代码演示如下:

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
38
39
40
41
42
43
44
/**
* 01-直接打印数组名称,得到的是数组对应的内存地址哈希值。
* 02-进制了解:二进制:01 十进制:0123456789 十六进制:0123456789abcdef
* 03-访问数组元素的格式:数组名称[索引值]。索引值:就是一个 int 数字,代表数组当中元素的编号。
* 04-【注意】索引值从 0 开始,一直到 “ 数组的长度 - 1 ”为 止。
* 05-使用动态初始化数组的时候,其中的元素将会自动拥有一个默认值。规则如下:
* 如果是整数类型,那么默认为 0;
* 如果是浮点类型,那么默认为 0.0;
* 如果是字符类型,那么默认为 '\u0000';
* 如果是布尔类型,那么默认为 false;
* 如果是引用类型,那么默认为 null。
* 06-注意事项:静态初始化其实也有默认值的过程,只不过系统自动马上将默认值替换成为了大括号当中的具体数值。
*/
public static void main(String[] args) {

// 静态初始化的省略格式
int[] array = {10, 20, 30};
System.out.println(array); // 内存地址值

// 直接打印数组当中的元素
System.out.println(array[0]); // 10
System.out.println(array[1]); // 20
System.out.println(array[2]); // 30
System.out.println("=============");

// 也可以将数组当中的某一个单个元素,赋值交给变量
int num = array[1];
System.out.println(num); // 20

// 动态初始化一个数组,使用动态初始化数组的时候,其中的元素将会自动拥有一个默认值,具体规则如顶部注释。
int[] array2 = new int[3];
System.out.println(array); // 内存地址值

System.out.println(array[0]); // 0
System.out.println(array[1]); // 0
System.out.println(array[2]); // 0
System.out.println("=================");

// 将数据 123 赋值交给数组 array 当中的 1 号元素
array2[1] = 123;
System.out.println(array[0]); // 0
System.out.println(array[1]); // 123
System.out.println(array[2]); // 0
}

数组常见的错误

数组一般会出现 两个常见错误数组越界异常空指针异常 。具体代码如下:

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
/**
* 01-数组的索引编号从 0 开始,一直到 “数组的长度 - 1” 为止。
* 02-如果访问数组元素的时候,索引编号并不存在,那么将发生:数组索引越界异常: ArrayIndexOutOfBoundsException
* 03-原因及解决方法:原因:索引编号写错了。解决方法:修改成为存在的正确索引编号。
* 04-所有的引用类型变量,都可以赋值为一个 null 值。但是代表其中什么都没有。
* 05-数组必须进行 new 初始化才能使用其中的元素。
* 06-如果只是赋值了一个 null,没有进行 new 创建,那么将会发生:空指针异常: NullPointerException
* 07-原因及解决方法:原因:忘了 new 。解决方法:补上 new
*/
public static void main(String[] args) {

int[] array = {15, 25, 35};
System.out.println(array[0]); // 15
System.out.println(array[1]); // 25
System.out.println(array[2]); // 35

// 错误写法:并不存在 3 号元素,所以发生数组越界异常
System.out.println(array[3]);

// 给数组 arr 赋值为 null
int[] arr = null;
System.out.println(arr[0]); // 报错:NullPointerException ,IDEA 会有提示

char[] ch = new char[]{'a', 'b', 'c'};
// 这里输出的不是字符数组 ch 的地址,而是abc,
// 因为 PrintStream 有多个重载的 println 方法,其中一个就是 public void println(char[] x),直接打印字符数组
System.out.println(ch);
// 如果要输出字符数组的地址,使用 toString() 方法
System.out.println(ch.toString());

}

数组的各种操作

第一种操作: 获取数组的长度 。代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {

// 静态初始化一个数组
int[] arr = {1, 2, 3, 4, 5, 6, 7};

// 获取数组的长度
int length = arr.length;

// 输出查看结果
System.out.println("数组的长度:" + length);

}

第二种操作: 数组的遍历输出 。代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {

// 静态初始化一个数组
int[] arr = {1, 2, 3, 4, 5, 6, 7};

// 第一种遍历方式: foreach
for (int i : arr) {
System.out.println(i);
}

// 第二种遍历方式 for
for (int i = 0; i < arr.length; i++) {
System.out.println("arr[" + i + "] = " + arr[i]);
}

}

第三种操作: 数组的最值获取 。代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void main(String[] args) {

// 静态初始化一个数组
int[] arr = {10, 2, 3, 40, 50, 6, 70};

int max = arr[0];
int min = arr[0];

for (int i = 1; i < arr.length; i++) {
// 获取最大值并保存于变量 max 中
if (arr[i] > max) {
max = arr[i];
}

// 获取最小值并保存于变量 min 中
if (arr[i] < min) {
min = arr[i];
}
}

System.out.println("数组中最小值为:" + min);
System.out.println("数组中最大值为:" + max);

}

第四种操作: 数组的反转 。代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main(String[] args) {

// 静态初始化一个数组
int[] arr = {1, 2, 3, 4, 5, 6, 7};

// 数组的反转
for (int left = 0, right = arr.length - 1; left < right; left++, right--) {
int temp;
temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}

// 数组的遍历
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}

}

第五种操作: 数组作为方法的参数 。代码演示如下:

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
public static void main(String[] args) {

// 静态初始化一个数组
int[] arr = {1, 2, 3, 4, 5, 6, 7};

// 调用 getMax() 方法,获取数组最大值
int max = getMax(arr);

// 输出查看结果
System.out.println("数组的最大值为:" + max);

}

// 使用数组作为方法的参数,获取数组的最大值
public static int getMax(int[] arr) {

int max = arr[0];

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

return max;

}

第六种操作: 数组作为返回值 。代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) {

// 调用 getArray() 方法获得数组
int[] arr = getArray(2, 3, 4);

// 打印查看结果
System.out.println(Arrays.toString(arr));

}

// 使用数组作为方法的返回值,从而得到一个数组
public static int[] getArray(int a, int b, int c) {
int[] arr = {a, b, c};
return arr;
}

数组的原理内存图

内存的概述

内存 是计算机中的重要原件,临时存储区域作用运行程序 。我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存。Java 虚拟机 要运行程序,必须要对内存进行空间的分配和管理。

Java中的内存划分

为了提高运算效率 ,就对内存空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。具体区域如下图:

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

Java内存图
一个数组的内存图
两个数组的内存图

两个引用指向同一个数组 的时候,他们操作的其实是 堆内的同一块区域 。先看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {

// 定义第一个数组
int[] arr1 = new int[]{12, 13, 14};
// 定义第二个数组
int[] arr2 = arr1;

// 两个数组的内存地址相同
System.out.println(arr1);
System.out.println(arr2);

// 改变数组的第三个元素
arr2[2] = 234;
System.out.println(arr1[2]);
System.out.println(arr2[2]);
}

两个引用指向同一数组的内存图

二维数组

概念和初始化

二维数组 就是 存储一维数组(内存地址/引用)的数组 。内存参考图如下:

二维数组的初始化 ,详见代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void main(String[] args) {

// 二维数组不是规则的矩阵
int[] arrayA[] = {{1, 2}, {2, 3, 4}, {3, 4, 5, 6}};
System.out.println(arrayA); // [[I@5e265ba4 两个[[表示是二维的,I表示数组是int型,@5e265ba4是内存地址

// 声明一个二维数组 arrayB ,用于存储 3 个一维数组,每一个一维数据存多少个数组,不知道 ,null
int[][] arrayB = new int[3][];

// 给 arrayB 赋值
arrayB[0] = new int[3]; // 3
arrayB[1] = new int[]{1, 2, 3, 4}; // 4
arrayB[2] = new int[2]; // 2

// 打印查看结果
System.out.println(arrayB[1]); // [I@156643d4
System.out.println(arrayB[1][1]); // 2

// 声明一个二维数组,同时创建出一维数组,每个一维数组的长度均相同
// 存储三个一维数组,每个一维数组的长度为 4
int[] arrayC[] = new int[3][4];
System.out.println(arrayC);

}

二维数组的遍历

二维数组的遍历如下:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
* @Author: guoshizhan
* @Create: 2020/3/3 23:19
* @Description: 二维数组的遍历
*/
public class ArrayTest {

public static void main(String[] args) {

// 定义一个二维数组 arr
int[] arr[] = {{1, 2}, {2, 3, 4}, {3, 4, 5, 6}};

// (1)普通 for 循环遍历
for (int i = 0; i < arr.length; i++) { // 0, 1, 2
for (int j = 0; j < arr[i].length; j++) { // 每一个一维数组的长度
System.out.print(arr[i][j] + "\t");
}
System.out.println();
}

// (2)加强 for 循环遍历
System.out.println("\n-------------------------");
for (int[] i : arr) {
for (int j : i) {
System.out.print(j + "\t");
}
System.out.println();
}


// (3)普通与加强 for 循环的混搭
System.out.println("\n-------------------------");
for (int[] ints : arr) { // 加强 for
for (int i = 0; i < ints.length; i++) {
System.out.print(ints[i] + "\t");
}
System.out.println();
}

// (3)普通与加强for循环的混搭
System.out.println("\n-------------------------");
for (int i = 0; i < arr.length; i++) {
for (int j : arr[i]) { // 加强 for
System.out.print(j + "\t");
}
System.out.println();
}

}

}

多维数组

声明一个数组,引用存在于栈中,new 出来的对象 存在堆中。三维数组及多维数组 一般很少用到,有用到时自己查吧!下面是一个 三维数组的创建和遍历输出 。代码如下:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**
* @Author: guoshizhan
* @Create: 2020/3/3 23:36
* @Description: 三维数组的遍历
*/
public class ArrayTest {

public static void main(String arg[]) {

// 创建一个三维数组 arr ,arr 存放了 3 个二维数组:arr[0]、arr[1]、arr[2]
int[][][] arr = new int[3][][];

// arr[0] ,存放了 3 个一维数组
arr[0] = new int[3][];
// arr[0][0] ,存放了 2 个数值
arr[0][0] = new int[2];
arr[0][0][0] = 1111;
arr[0][0][1] = 1112;
// arr[0][1] ,存放了 2 个数值
arr[0][1] = new int[2];
arr[0][1][0] = 1121;
arr[0][1][1] = 1122;
// arr[0][2] ,存放了 3 个数值
arr[0][2] = new int[3];
arr[0][2][0] = 1131;
arr[0][2][1] = 1132;
arr[0][2][2] = 1133;


// arr[1] ,存放了 3 个一维数组
arr[1] = new int[3][];
// arr[1][0] ,存放了 2 个数值
arr[1][0] = new int[2];
arr[1][0][0] = 1211;
arr[1][0][1] = 1212;
// arr[1][1] ,存放了 2 个数值
arr[1][1] = new int[2];
arr[1][1][0] = 1221;
arr[1][1][1] = 1222;
// arr[1][2] ,存放了 2 个数值
arr[1][2] = new int[2];
arr[1][2][0] = 1231;
arr[1][2][1] = 1232;


// arr[2] ,存放了 3 个一维数组
arr[2] = new int[3][];
// arr[2][0] ,存放了 2 个数值
arr[2][0] = new int[2];
arr[2][0][0] = 1311;
arr[2][0][1] = 1312;
// arr[2][1] ,存放了 2 个数值
arr[2][1] = new int[2];
arr[2][1][0] = 1321;
arr[2][1][1] = 1322;
// arr[2][2] ,存放了 2 个数值
arr[2][2] = new int[2];
arr[2][2][0] = 1331;
arr[2][2][1] = 1332;

// 使用增强 for 循环输出结果
for (int[][] a2 : arr) {
for (int[] a1 : a2) {
for (int a: a1) {
System.out.print(a + "\t");
}
System.out.println();
}
System.out.println();
}

}

}

类与面向对象

面向对象思想概述

面向对象概述

Java 语言 是一种 面向对象 的程序设计语言,而面向对象思想是一种程序设计思想。我们在面向对象思想的指引下,使用 Java 语言去设计、开发计算机程序。这里的对象泛指现实中一切事物,每种事物都具备自己的属性和行为 。面向对象思想就是在计算机程序设计过程中,参照现实中事物,将事物的 属性特征、行为特征 抽象出来,描述成计算机事件的设计思想。它区别于 面向过程思想面向对象思想 强调的是通过调用对象的行为来实现功能,而不是自己一步一步的去操作实现。

面向对象举例

洗衣服:
面向过程:把衣服脱下来 --> 找一个盆 --> 放点洗衣粉 --> 加点水 --> 浸泡10分钟 --> 揉一揉 --> 清洗衣服 --> 拧干 --> 晾起来 面向对象:把衣服脱下来 --> 打开全自动洗衣机 --> 扔衣服 --> 按开关 --> 晾起来
面向过程和面向对象的区别:
面向过程:强调步骤。 面向对象:强调对象,这里的对象就是洗衣机。

面向对象特点

面向对象思想 是一种更符合我们思考习惯的思想,它可以 将复杂的事情简单化 ,并将我们从执行者变成了指挥者。面向对象的语言中,包含了 三大基本特征:即 封装继承多态 。这三大特性以后详细讲。

类和对象

环顾周围,你会发现很多 对象 ,比如 桌子,椅子,同学,老师 等。桌椅属于办公用品,师生都是人类。那么什么是类呢?什么是对象呢?

什么是类

类: 是一组相关属性和行为的集合 。可以看成是一类事物的 模板 ,使用事物的 属性特征和行为特征 来描述该类事物。现实中,我们可以这样描述一类事物 (属性 + 行为)属性 就是该事物的状态信息行为 就是该事物能够做什么

类的举例:
举例:小猫。 属性:名字、体重、年龄、颜色。 行为:走、跑、叫。

类的定义格式

类的定义格式:
定义类:就是定义类的成员,包括成员变量和成员方法。 成员变量:和以前定义变量几乎是一样的。只不过位置发生了改变。在类中,方法外。 成员方法:和以前定义方法几乎是一样的。只不过把static去掉,static的作用在面向对象后面课程中再详细讲解。

类的定义格式 代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Student{
// 成员变量
String name; // 姓名
int age; // 年龄

// 定义成员方法 study()
public void study(){
System.out.println("好好学习,天天向上");
}
// 定义成员方法 eat()
public void eat(){
System.out.println("学习饿了要吃饭");
}
}

事物与类的对比

现实世界的一类事物:
属性:事物的状态信息。 行为:事物能够做什么。
Java 中用 class 描述事物也是如此:
成员变量:对应事物的属性 成员方法:对应事物的行为

什么是对象

对象: 是一类事物的具体体现 。对象是类的一个实例(对象并不是找个女朋友),必然具备该类事物的 属性和行为 。现实中,一类事物的一个实例就是对象 :一只小猫。属性: tom、5kg、2years、yellow。行为: 溜墙根走、蹦跶的跑、喵喵叫。

类与对象的关系

类与对象的关系:
类是对一类事物的描述,是抽象的。 对象是一类事物的实例,是具体的。 类是对象的模板,对象是类的实体。

举个例子,手机模板抽象的 ,不能被人使用,这个叫做 。但是 通过模板做成的手机具体的 ,可以被使用,叫做 对象 ,也叫 实体 。参考图如下:

对象的使用

对象的使用格式

第一步: 了解 创建对象格式 以及 对象访问类中成员格式 ,如下:

1
2
3
4
5
6
7
8
9
10
11
# 创建对象格式
类名 对象名 = new 类名();


#对象访问类中成员格式

# 访问成员变量
对象名.成员变量;

# 访问成员方法
对象名.成员方法();

第二步: 创建 Student 实体类 ,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Student {

public int age;
public String name;

public void study() {
System.out.println("好好学习,天天向上");
}

public void eat() {
System.out.println("学习饿了要吃饭");
}

}

第三步: 创建 Student 类的测试类 StudentTest ,用于创建 Student 类的 对象 并访问其 成员变量及成员方法 ,代码如下:

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
public class StudentTest {

public static void main(String[] args) {

// 创建对象格式:类名 对象名 = new 类名();
Student stu = new Student();
System.out.println("stu:" + stu);
System.out.println("‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐");

// 直接输出成员变量值
System.out.println("姓名:" + stu.name); // null
System.out.println("年龄:" + stu.age); // 0
System.out.println("‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐");

// 给成员变量赋值
stu.name = "赵丽颖";
stu.age = 18;

// 再次输出成员变量的值
System.out.println("姓名:" + stu.name); // 赵丽颖
System.out.println("年龄:" + stu.age); // 18
System.out.println("‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐");

// 调用成员方法
stu.study(); // "好好学习,天天向上"
stu.eat(); // "学习饿了要吃饭"

}

}

成员变量的默认值

数据类型 默认值
整数(byte,short,int,long) 0
浮点数(float,double) 0.0
字符(char) ‘\u0000’
布尔(boolean) false
数组,类,接口 null

类和对象的练习

第一步: 定义一个 手机类 Phone ,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Phone {

// 成员变量
String brand; // 品牌
double price; // 价格
String color; // 颜色

// 成员方法
public void call(String name) {
System.out.println("给" + name + "打电话");
}

public void sendMessage() {
System.out.println("群发短信");
}

}

第二步: 定义一个 测试类 PhoneTest ,代码如下:

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
public class PhoneTest {

public static void main(String[] args) {

// 根据 Phone 类,创建一个名为 one 的对象
// 格式:类名称 对象名 = new 类名称();
Phone one = new Phone();
System.out.println(one.brand); // null
System.out.println(one.price); // 0.0
System.out.println(one.color); // null
System.out.println("=========");

one.brand = "苹果";
one.price = 8388.0;
one.color = "黑色";

System.out.println(one.brand); // 苹果
System.out.println(one.price); // 8388.0
System.out.println(one.color); // 黑色
System.out.println("=========");

one.call("乔布斯"); // 给乔布斯打电话
one.sendMessage(); // 群发短信

}

}

对象内存图

一个对象

两个对象

作为参数

作为返回值

成员变量与局部变量

两者概念

成员变量 分为 类变量(static修饰)实例变量(无static)类变量 可以直接使用类名调用,实例变量 需要 创建对象 才能使用。局部变量 是定义在方法里或定义在方法的参数位置 。它们的具体区别如下:

两者区别

在类中的位置不同:
成员变量:类中,方法外 局部变量:方法中或者方法声明上(形式参数)
作用范围不一样:
成员变量:类中 局部变量:方法中
初始化值的不同:
成员变量:有默认值 局部变量:没有默认值,必须先定义,赋值,最后使用
在内存中的位置不同:
成员变量:堆内存 局部变量:栈内存
生命周期不同:
成员变量:随着对象的创建而存在,随着对象的消失而消失 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失

封装特性

封装概述

面向对象 编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改。封装 可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。 要访问该类的数据,必须通过指定的方式。适当的封装可以让代码更容易理解与维护,也加强了代码的安全性

原则: 将属性隐藏起来,若需要访问某个属性,提供公共方法对其访问。
封装步骤: ① 使用 private 关键字 来修饰成员变量。② 对需要访问的成员变量,提供对应的 一对 getxxx 方法、 setxxx 方法

private 关键字

private 的含义:
private 是一个权限修饰符,代表最小权限。 可以修饰成员变量和成员方法。 被 private 修饰后的成员变量和成员方法,只在本类中才能访问。

使用 private 修饰成员变量 ,代码如下:

1
2
3
4
5
6
7
public class Student{

// private 的使用格式:private 数据类型 变量名;
private String name;
private int age;

}

提供 getxxx 方法/ setxxx 方法 ,可以访问成员变量,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Student {

private String name;
private int age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

}

this 关键字

请看下面一段代码,看是否会出现问题。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Student{

private String name;
private int age;

public void setName(String name){
name = name;
}

public void setAge(int age){
age = age;
}

}

经过测试,我们发现了一个问题,成员变量赋值失败了 。也就是说,在修改了的形参变量名后,方法并没有给成员变量赋值!这是由于 形参变量名与成员变量名重名 ,导致成员变量名被隐藏,方法中的变量名,无法访问到成员变量,从而赋值失败。所以,我们只能使用 this 关键字,来解决这个重名问题。this 代表所在类的当前对象的引用(地址值) ,即对象自己的引用。方法被哪一个对象调用,方法中的 this 就代表那个对象。即谁在调用,this 就代表谁。代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Student {

private String name;
private int age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

// this 使用格式:this.成员变量名;
public int getAge() {
return age;
}

// this 使用格式:this.成员变量名;
public void setAge(int age) {
this.age = age;
}

}

构造方法

当一个对象被创建时候,构造方法 用来 初始化该对象,给对象的成员变量赋初始值

小提示:

无论你与否自定义构造方法,所有的类都有构造方法 。因为 Java 会 自动提供了一个无参数构造方法 。一旦自己定义了构造方法,那么 Java 自动提供的默认无参数构造方法就会失效,除非自己再重新定义一个无参构造方法。

构造方法在写法上,方法名与它所在的类名相同 。它没有返回值,所以不需要返回值类型,甚至不需要 void 。代码演示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 构造方法的格式:
* 修饰符 构造方法名(参数列表) {
* //方法体
* }
*/
class Student {

private String name;
private int age;

public Student() { // 无参构造
}

public Student(String name, int age) { // 有参构造
this.name = name;
this.age = age;
}

}
注意事项:
1、如果你不提供构造方法,系统会给出无参数构造方法。 2、如果你提供了构造方法,系统将不再提供无参数构造方法。 3、构造方法是可以重载的,既可以定义参数,也可以不定义参数。

标准代码 JavaBean

JavaBean 是 Java 语言编写类的一种 标准规范 。符合 JavaBean 的类,要求 类必须是具体的和公共的,并且具有无参数的构造方法 ,还需要提供用来操作成员变量的 getxxx 和 setxxx 方法

1
2
3
4
5
6
7
8
9
10
11
public class ClassName{

// 成员变量
// 构造方法
// 无参构造方法【必须】
// 有参构造方法【建议】
// 成员方法
// getXxx()
// setXxx()

}

编写符合 JavaBean 规范的类,以学生类为例,标准代码如下:

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
class Student {

// 成员变量
private String name;
private int age;

// 无参构造方法
public Student() {
}

// 有参构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
}

// getxxx 和 setxxx 方法
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

到此为止,Java 基础(上篇) 就结束了,接下来相关的文章是 Java 基础(中篇)

    / 

📚 本站推荐文章
  👉 从 0 开始搭建 Hexo 博客
  👉 计算机网络入门教程
  👉 数据结构入门
  👉 算法入门
  👉 IDEA 入门教程

可在评论区留言哦

一言句子获取中...

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×