初识Java语言
什么是计算机编程语言
- 人类语言:人与人之间用于沟通的一种方式,例如中国人与中国人用普通话沟通,而中国人要和外国人交流,要学习外语
- 计算机语言:人与计算机之间进行交流和沟通的工具,用于描述计算机所需执行的任务和操作
计算机语言的演变
计算机语言的发展历史可以追溯到计算机诞生之初。随着计算机技术的不断进步和发展,计算机语言也经历了多个阶段的演变。
- 机器语言时代:计算机最早只能理解机器语言,即由0和1组成的二进制代码。但是,编写和理解机器语言代码非常困难且容易出错。
- 汇编语言时代:为了简化程序员的工作,汇编语言应运而生。汇编语言使用助记符(mnemonics)代替了二进制指令,使得代码更易读写,但仍然需要直接操作底层硬件。
- 高级语言的出现:20世纪50年代和60年代,高级语言开始出现。这些语言提供了比机器语言和汇编语言更高层次的抽象,使得程序员可以更容易地编写和理解代码。FORTRAN、COBOL、ALGOL等是早期的高级语言。它们大幅度提高了代码的可读性,但仍然需要通过编译器将高级代码转换为机器语言来执行。
- C语言的崛起:20世纪70年代,C语言是由贝尔实验室的Dennis Ritchie在开发的,它结合了高级语言和底层编程的特性,既能高效地操作底层硬件,又提供了高级语言的抽象和易用性。C语言的成功大大推动了计算机科学的发展,并成为后来许多编程语言的基础。在高级语言中,C语言的出现具有里程碑意义。
- 面向对象语言的兴起:20世纪80年代和90年代,面向对象编程(OOP)成为主流。面向对象语言允许程序员通过定义对象和对象之间的关系来组织代码,以更好地表达问题的解决方案。Smalltalk、C++和Objective-C等语言在这个时期得到广泛应用。
- Java的诞生:Java语言由Sun Microsystems(现为Oracle)于1995年发布。Java是一种完全面向对象的语言,它强调可移植性、安全性和简洁性。Java通过引入Java虚拟机(JVM)实现了跨平台的能力,使得同一份Java代码可以在不同的操作系统上运行。

Java语言特点
- 简单易学:Java的语法相对简单,与其他编程语言相比,更易于理解和学习。
- 面向对象:Java是一种完全面向对象的语言,支持封装、继承和多态等面向对象的特性。
- 平台无关性:Java通过Java虚拟机(JVM)实现了平台无关性,即一次编写程序在任何支持Java的平台上都可以运行,而不需要重新编译。
- 内存管理:Java具有自动内存管理机制,开发人员不需要手动管理内存,垃圾收集器会自动回收不再使用的对象。
- 强类型语言:Java是一种静态类型语言,所有变量在使用之前必须声明类型,并且类型检查是在编译过程中进行的,从而提高了代码的稳定性和可靠性。
- 多线程支持:Java提供了多线程编程的支持,可以轻松地创建和管理多个线程,实现并发执行。
- 异常处理:Java提供了异常处理机制,可以捕获和处理程序中的异常情况,增加了程序的健壮性和容错性。
- 安全性:Java具有强大的安全性特性,包括通过类加载器实现的安全沙箱机制、访问控制和权限管理等。
- 开放性:Java有一个庞大的开源社区,提供了大量的开源库和框架,使开发人员可以快速构建功能丰富的应用程序。
Java体系平台
随着Java技术的不断发展,Java体系的平台也在不断完善和更新,主要平台如下
| 平台名称 | 特点 | 应用 | 示例 |
|---|
| 核心 Java (Java SE) | 提供语言基础、核心库和虚拟机 | 独立应用程序、桌面应用程序 | 文本编辑器、图形界面应用 |
| 企业级 Java (Java EE) | 在Java SE的基础上提供企业级功能和框架 | 大规模、复杂的企业应用程序 | 电子商务平台、客户关系管理系统 |
| 移动端 Java (Java ME) | 面向嵌入式系统、移动设备等领域 | 手机游戏、移动端应用、嵌入式设备 | 手机游戏、移动应用、智能设备 |
JDK、JRE、JVM简介
JDK提供了开发Java程序所需的工具和资源;JRE提供了运行Java程序所需的最小环境;而JVM则是Java程序的运行平台
- JVM:
Java虚拟机,负责解释和执行Java字节码 - JRE:
Java运行时环境,是在计算机上执行Java应用程序所需的最小环境,包含JVM和类库。JRE = JVM + JavaSE标准类库 - JDK:
Java开发工具包,它包含了用于开发、编译和调试Java程序的工具。JDK = JRE + 开发工具集

Java基础知识
注释
注释是对代码的简要说明,是给程序员看的
扩展说明:文档注释中的内容可以使用javadoc生成单独的帮助文档,这样可以方便一些开发者查阅,在命令提示符中输入下面命令
1
| javadoc –d 目标目录 java文件文件名
|
程序的入口main()方法
在Java程序中,main()方法是程序的入口点。它是程序执行的起始位置,是Java虚拟机(JVM)调用的第一个方法,在main()方法内部,可以编写程序的逻辑代码,包括变量声明、方法调用、条件语句、循环等等。当程序运行时,JVM会从main()方法开始执行。
1 2 3
| public static void main(String[] args) { }
|
HelloWorld入门案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); System.out.print("Hello World!"); } }
|
关键字与保留字
关键字:被Java语言赋予了特殊含义,用做专门用途的字符串(单词) ,关键字中所有字母都为小写
1 2 3 4
| abstract assert boolean break byte case catch char class continue default do double else enum extends final finally float for if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while
|
保留字:现有Java版本尚未使用,但以后版本可能会作为关键字使用。自己命名标识符时要避免使用这些保留字
字面量
字面量是用于表达一个固定值的直接写法,Java中常见的字面量类型:
- 整数字面量:用于表示整数值,可以是十进制、二进制、八进制或十六进制。例如:10、0b101、012、0xFF。
- 浮点数字面量:用于表示浮点数值,包括带小数点的十进制数和科学计数法表示的数。例如:3.14、1.23e-5。
- 字符字面量:用单引号括起来的单个字符。例如:’a’、’7’、’%’。
- 字符串字面量:用双引号括起来的一串字符。例如:”Hello, World!”。
- 布尔字面量:用于表示布尔值,只有两个取值:true和false。
- null字面量:表示空引用。
虽然使用字面量可以方便地直接指定数值或数据,但字面量会掩盖语句的真实意义。
假设有如下这样一行代码,其中 result 和 value 是假设的变量,而 5 是字面量
如果只是看到这行代码,我们并不清楚 5 代表什么含义,很难准确理解这个数字的用途
常量
为了解决字面量带来的问题,Java语言允许为不会改变的值,分配一个描述性的名字,这种名字称为常量。
在Java中定义常量的方式是使用关键字final
按照命名规范使用大写字母表示常量,示例如下
1 2 3
| final int MAX_VALUE = 100; final double PI = 3.14159; final String MESSAGE = "Hello, World!";
|
对于之前的问题,我们可以定义一个名为 INCREMENT 的常量,将其赋值为 5,然后使用 result = value + INCREMENT; 来表示相同的操作。
1 2
| final int INCREMENT = 5; result = value + INCREMENT;
|
标识符
程序员写代码时自己定义的一些名字,包括类名、方法名、字段名、变量名等等,通常情况下会使用英文来进行标识符的命名,以下是Java中标识符的一些规则:
- 字母、数字和下划线:标识符可以由字母(A-Z或a-z)、数字(0-9)和下划线(_)组成,但不能以数字开头。
- 大小写敏感:Java是大小写敏感的,所以大写字母和小写字母被视为不同的字符。例如,”myVariable”和”myvariable”是两个不同的标识符。
- 长度无限制:标识符的长度可以是任意长。
- 不能使用关键字:不能使用Java的保留关键字作为标识符,如if、while、class等。
- 规范命名约定:为了提高代码的可读性,推荐使用驼峰命名法,即将多个单词连接起来,除第一个单词外的每个单词首字母大写,例如myVariable、calculateTotal等。
- 合理取名:标识符应该具有描述性,能够清晰表示其意义和用途。
包(package)
(1)在Java语言里面,开发者难免会编写出同名的类,为了便于区分,就这类前加前缀加以区分,这个前缀就是包(package)
(2)包(package)类似一个文件夹,可以用来将相关的类组织在一起,避免命名冲突,并提供访问控制的功能
- 组织类:通过将相关的类放在同一个包中,可以更好地组织和管理代码。
- 避免命名冲突:不同包下可以存在同名的类,避免了命名冲突的问题。
- 访问控制:包是访问控制的基本单位,使用访问修饰符可以限制类、变量和方法的访问范围。
(3)为了将类放入特定的包中,需要在Java源文件的开头使用package关键字指定包名
(4)在Java中,为了能够使用某一个包的成员,我们需要在 Java 程序中明确导入该包,可以使用import关键字来导入类和包
1 2 3 4
| import org.junit.Test;
import java.io.*;
|
(5)包的命名规范
- 避免使用Java关键字和保留字作为包名
- 包名一般使用小写字母,并且以字母开头,避免使用数字开头,多个单词可以用
.分隔 - 一般会使用公司域名反转的方式命名(例如:
com.example.mypackage)
Java跨平台的原理
Java跨平台是指使用Java编写的程序可以在不同的操作系统和硬件平台上运行,而无需进行太多修改或重新编译。这得益于Java虚拟机(JVM)的存在,它充当了中间层,能够解释和执行Java字节码,并将其转化为特定平台上的机器指令。因此,只要在目标平台上安装了相应的JVM,Java程序就可以顺利运行

Java程序的编写(编写期)
在编写期,Java程序员主要做的事情就是使用Java编程语言编写以.java结尾的文件,我们称之为源文件(source file),把在源文件里面所编写的代码叫做源代码(source code)
Java程序的编译(编译期)
源文件(.java文件)主要是给程序员看的,而Java虚拟机看不懂源文件中的源代码,但程序员可以使用Java编译器(javac)将Java源代码编译成Java虚拟机看的懂的以.class结尾的字节码文件。
1
| javac -encoding UTF-8 HelloWorld.java
|
编译器将Java源代码转换为字节码的过程中,会进行词法分析、语法分析、语义检查等步骤,以确保代码的正确性和合法性,如果源代码中存在错误或不符合语法规范,编译器会生成相应的错误信息进行提示,不会生成字节码文件(.class文件),此时需要我们根据错误提示的信息去分析和解决。这些在编译过程中发现的错误被称为编译期错误(Compile-time Errors)或者语法错误(Syntax Errors)
Java程序的运行(运行期)
在运行期,Java虚拟机(JVM)会加载并解释字节码文件,并将其转换为特定平台上的机器指令,以实现程序的运行
这个时期如果出现了错误,我们称之为运行期错误,运行期错误也会出现一些提示信息,我们需要根据这些提示信息去定位并解决问题。
变量
变量简介
(1)变量是内存中的一个存储区域,该区域的数据可以在同一类型范围内不断变化
(2)变量是程序中最基本的存储单元,包含变量类型、变量名和存储的值
(3)变量的作用域是定义所在的一对{ }内,只有在其作用域内才有效,同一个作用域内,不能定义重名的变量
变量的声明
语法:数据类型 变量名称;
变量的赋值
语法:变量名称 = 值;
变量的声明和赋值
语法:数据类型 变量名称=值;
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Demo { public static void main(String[] args) { byte a = 1; short b = 2; int c = 3; long d = 4; float e = 5.5f; double f = 6.5; char g1 = '\t'; char g2 = '\u0043'; boolean h1 = true; boolean h2 = false; } }
|
成员变量
成员变量是定义在类中、方法外部的变量。它们属于对象的属性,每个对象都有自己的一份成员变量副本。成员变量可以根据需要被赋予不同的值,并且在整个对象的生命周期内保持有效。如果没有显式地赋初始值,成员变量会被赋予默认值(具体取决于数据类型)
1 2 3 4 5 6 7 8 9 10
| public class Person { String name = "小明"; int age = 20; public void display() { System.out.println("Name: " + name); System.out.println("Age: " + age); } }
|
局部变量
局部变量是定义在方法、构造函数或代码块内部的变量。它们属于方法或代码块的局部范围,只在定义它们的作用域内可见。局部变量必须显式地初始化,否则编译器会报错。局部变量的生命周期仅限于所在的方法、构造函数或代码块的执行期间
1 2 3 4 5 6 7
| public class Example { public void print() { int count = 10; System.out.println("Count: " + count); } }
|
数据类型
Java中的数据类型包括基本数据类型和引用数据类型,它们在内存中占据不同的空间大小,用于存储不同种类的数据。

基本数据类型
注意:String类型不属于基本数据类型,它是jdk中封装好的一个类,数据转换时需要调用String类中相应的方法
| 数据类型 | 简介 |
|---|
| 整型 | byte、short、int、long |
| 浮点型 | float、double |
| 字符型 | char |
| 布尔型 | boolean |
整型
| 类型 | 占用存储空间(字节) | 默认值 | 概括 |
|---|
| byte(字节) | 1 | 0 | 计算机中基本存储单元。 |
| short(短整型) | 2 | 0 | 短整型数据类型 |
| int(整型) | 4 | 0 | 整型常量默认为 int 型,变量通常声明为int型 |
| long(长整型) | 8 | 0L | 声明long型常量须在后加‘l’或‘L’,除非不足以表示较大的数,才使用long |
浮点型
浮点型常量默认为double型,声明float型常量,须后加‘f’或‘F’
| 类型 | 占用存储空间(字节) | 默认值 | 概括 |
|---|
| float(单精度浮点型) | 4 | 0.0f | 单精度,尾数可以精确到7位有效数字,很多情况下,精度很难满足需求。 |
| double(双精度浮点型) | 8 | 0.0d | 双精度,精度是float的两倍 |
字符类型
| 类型 | 占用存储空间(字节) | 默认值 | 概括 |
|---|
| char(字符型) | gbk / gb2312 是2字节,utf-8 是3字节 | ‘\u0000’(空字符) | 表示单个字符,使用Unicode编码 |
布尔类型
| 类 型 | 占用存储空间(字节) | 默认值 | 概括 |
|---|
| boolean(布尔型) | 1 | false | 用来判断逻辑条件,一般用于程序流程控制,只允许取值true和false,无null |
引用数据类型
简单来说,所有的非基本数据类型都是引用数据类型,例如类、接口、数组、枚举、注解、字符串等
数据类型转换
基本数据类型转换
在Java中,数据类型转换可以分为两种:隐式转换(自动类型转换)和显式转换(强制类型转换)
其中boolean 类型与其他七种类型的数据都不能进行转换,其他数据类型之间可以进行转换,但可能存在精度损失或其他一些变化
自动转换(隐式)
(1)数据范围小的数值赋值给另一个数据范围大的变量,这种转换方式是自动的,不会造成信息丢失, 也可以叫作隐式转换
(2)自动转换按从低到高的顺序转换,不同类型数据间的优先关系如下
1 2
| byte → short → int → long → float → double char → int → long → float → double
|

(3)对于需要转换的数据类型,必须是转换前的数据类型兼容转换后的数据类型,对于转换后的数据类型的范围,必须比转换前的数据类型范围大。
(4)自动转换案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Demo { public static void main(String[] args){ int num1 = 10; double num2 = num1;
float decimal1 = 3.14f; double decimal2 = decimal1;
byte A = 2; int B = 129; int C = A + B; System.out.println(C); } }
|
(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
|
public class Test { public static void main(String[] args) { byte b = 10; test(b); }
private static void test(byte b) { System.out.println("11111"); }
private static void test(short b) { System.out.println("22222"); }
private static void test(char b) { System.out.println("33333"); }
private static void test(int b) { System.out.println("44444"); } }
|
强制转换(显式)
(1)数据范围大的数值赋值给另一个数据范围小的变量,需要自己转换,可能会造成数据丢失或精度损失。
(2)强制转换规则如下
1 2
| 数值型数据的转换:byte -> shart -> int -> long -> float -> double 字符型转换为整型:char -> int
|
(3)强制转换的格式是在需要转型的数据前加上操作符( ),然后在括号内加入需要转化的数据类型。
1 2 3 4 5 6 7 8 9
| public class Demo { public static void main(String[] args){ double decimal = 3.14159; int num = (int) decimal;
long largeNum = 10000000000L; int smallNum = (int) largeNum; } }
|
(4)需要注意的是,有的数据经过转型运算后,精度会丢失,而有的会更加精确
1 2 3 4 5 6 7 8
| public class Demo { public static void main(String[] args){ int x = (int) 12.34 + (int) 56.7; double y = (double) 10 + (double) 10; System.out.println("x=" + x); System.out.println("y=" + y); } }
|
引用数据类型转换
对于引用数据类型,当进行类型转换时,通常是通过继承、接口实现或类型转换操作符来实现的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class Animal { public void sound() { System.out.println("Animal makes a sound"); } }
class Dog extends Animal { public void sound() { System.out.println("Dog barks"); }
public void fetch() { System.out.println("Dog fetches the ball"); } }
Animal animal = new Dog(); animal.sound();
Dog dog = (Dog) animal; dog.sound(); dog.fetch();
|
运算符
运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等
算数运算符
| 运算符 | 简介 |
|---|
| + | 加、正号、字符串连接 |
| - | 减、负号 |
| * | 乘 |
| / | 除 |
| % | 取模(取余) |
| ++ | 自增前,先运算,后取值 自增后,先取值,后运算 |
| – | 自减前,先运算,后取值 自减后,先取值,后运算 |
赋值运算符
比较运算符(关系运算符)
比较运算符的结果都是boolean型,也就是要么是true,要么是false
| 运算符 | 简介 |
|---|
| == | 相等于 |
| != | 不等于 |
| > | 大于 |
| < | 小于 |
| >= | 大于等于 |
| <= | 小于等于 |
| Instanceof | 检查是否为类的对象 |
逻辑运算符
| 运算符 | 简介 |
|---|
& | 按位与 |
&& | 短路与 |
| ` | ` |
| ` | |
! | 逻辑非 |
^ | 逻辑异或 |
位运算符
位运算符是直接对整数的二进制的运算
| 运算符 | 简介 |
|---|
| << | 左移 |
| >> | 右移 |
| >>> | 无符号右移 |
| & | 与运算 |
| | | 或运算 |
| ^ | 异或运算 |
| ~ | 取反算值 |
三元运算符
三元运算符(三目运算符)由三个部分组成,先执行条件表达式,然后根据条件表达式的结果选择执行表达式1还是表达式2。
- 条件表达式的结果为 true:执行表达式1。
- 条件表达式的结果为 false:执行表达式2。
相关问题
&与&&的区别?
&表示按位与,可以用于布尔类型或者整数类型。
1 2 3 4 5 6 7 8 9 10 11
| public class Demo { public static void main(String[] args) { boolean a = true; boolean b = false; System.out.println(a & b);
int x = 5; int y = 3; System.out.println(x & y); } }
|
&&表示短路与,只能用于两个布尔类型。
- 布尔类型:对于布尔类型,当第一个操作数为
false时,不会对第二个操作数进行求值,直接返回false,因此它可以避免不必要的计算。
1 2 3 4 5 6 7
| public class Demo { public static void main(String[] args) { boolean a = false; boolean b = true; System.out.println(a && b); } }
|
|与||的区别?
|表示按位或,可以用于布尔类型或者整数类型。
- 布尔类型:对于布尔类型,当两个操作数中至少有一个为
true时,结果为true,否则结果为false。 - 整数类型:对于整数类型,会将两个操作数的二进制表示的每一位进行逻辑或运算,得到的结果为一个新的整数。
1 2 3 4 5 6 7 8 9 10 11
| public class Demo { public static void main(String[] args) { boolean a = true; boolean b = false; System.out.println(a | b);
int x = 5; int y = 3; System.out.println(x | y); } }
|
||表示逻辑或,只能用于两个布尔类型。
- 布尔类型:当第一个操作数为
true时,不会对第二个操作数进行求值,直接返回true,因此它可以避免不必要的计算。
1 2 3 4 5 6 7
| public class Demo { public static void main(String[] args) { boolean a = true; boolean b = false; System.out.println(a || b); } }
|
=与==的区别?
=是赋值运算符,用于将右侧的值赋给左侧的变量
1 2 3 4 5 6 7 8
| public class Demo { public static void main(String[] args) { int a = 10; int b = 20; int c = a + b; System.out.println(c); } }
|
==是相等运算符,用于比较两个操作数的值(对于基本数据类型)或对象引用(对于引用类型)是否相等,并返回一个布尔值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Demo { public static void main(String[] args) { int x = 5; int y = 3; boolean result1 = (x == y); System.out.println(result1);
String str1 = "Hello"; String str2 = "Hello"; boolean result2 = (str1 == str2); System.out.println(result2);
String str3 = new String("Hello"); String str4 = new String("Hello"); boolean result3 = (str3 == str4); System.out.println(result3); } }
|
流程控制
流程控制简介
流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块
| 流程结构 | 简介 |
|---|
| 顺序结构 | 程序从上到下逐行地执行,中间没有任何判断和跳转 |
| 分支结构 | 根据条件,选择性地执行某段代码。 有if…else和switch-case两种分支语句。 |
| 循环结构 | 根据循环条件,重复性的执行某段代码。 有for、while、do…while三种循环语句。 |
顺序结构
Java中定义成员变量时采用合法的前向引用
1 2 3 4 5 6 7 8 9 10
| public class Demo { public static void main(String[] args){ int num1 = 12; int num2 = num1 + 2; System.out.println(num2); ... } }
|
分支结构
if-else
(1)单分支
(2)双分支
1 2 3 4 5
| if(条件表达式){ 执行代码块1; } else{ 执行代码块2; }
|
(3)多分支
1 2 3 4 5 6 7 8 9
| if(条件表达式1){ 执行代码块1; } else if (条件表达式2){ 执行代码块2; } else if (条件表达式n) { 执行代码块n; }else{ 执行代码块n; }
|
switch-case
(1)switch-case语法
1 2 3 4 5 6 7 8 9 10 11 12 13
| switch (表达式/变量) { case 常量1: 执行语句1; case 常量2: 执行语句2; case 常量3: 执行语句3; case 常量n: 执行语句n; ... ... ... default: 以上情况都不满足时执行语句; }
|
(2)使用案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class Test { public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.println("请输入数字10或20"); String next = scan.next(); int i = Integer.parseInt(next); switch (i) { case 10: System.out.println("输入了10"); break; case 20: System.out.println("输入了20"); break; default: System.out.println("输入错误"); break; } } }
|
循环结构
for
1 2 3 4
| for (①初始化部分;②循环条件部分;④迭代部分){ ③循环体部分; }
|
代码示例
1 2 3
| for (int i = 0; i < 5; i++) { }
|
foreach
JDK1.5提供了foreach循环,方便的遍历集合、数组元素,语法结构如下
1 2 3
| for (集合或数组的类型 局部变量:集合或数组对象) { }
|
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Demo { public static void main(String[] args) { String[] arrs = {"A", "B", "C"}; for (String arr : arrs) { System.out.println(arr); } List<String> asList = Arrays.asList("AA", "BB", "CC"); for (Object obj : asList) { System.out.println(obj); } } }
|
while
在每次迭代之前,先判断循环条件是否为真。如果条件为真,则执行循环体内的代码,然后再次判断条件。只有当条件为假时,循环停止执行。
1 2 3 4 5 6
| ①初始化部分 while(②循环条件部分){ ③循环体部分; ④迭代部分; }
|
do-while
在每次迭代之后,再判断循环条件是否为真。首先执行循环体内的代码,然后再判断条件是否为真。只有当条件为真时,循环会继续执行;否则,循环停止执行。
1 2 3 4 5 6
| ①初始化部分; do { ③循环体部分 ④迭代部分 } while (②循环条件部分);
|
嵌套循环(多重循环)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Demo { public static void main(String[] args) { for (int i = 1; i <= 9; i++) { for (int j = 1; j <= 9; j++) { System.out.print(i + "*" + j + "=" + i * j); System.out.print(" "); } System.out.println(); } } }
|
流程控制相关关键字
break(结束当前循环)
break语句只能用于switch语句和循环语句中,用于终止某个语句块的执行,结束当前循环
1 2 3 4 5 6
| for (int i = 0; i < 10; i++) { if (i == 5) { break; } System.out.println(i); }
|
continue(结束当次循环)
continue语句只能使用在循环结构中,结束当次循环,continue语句用于跳过其所在循环语句块的一次执行,继续下一次循环
1 2 3 4 5 6
| for (int i = 0; i < 10; i++) { if (i == 5) { continue; } System.out.println(i); }
|
continue语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环
1 2 3 4 5 6 7 8
| for (int i = 0; i < 5; i++) { for (int j = 0; j < 3; j++) { if (j == 1) { continue; } System.out.println("i: " + i + ", j: " + j); } }
|
return(结束一个方法)
return语句并非专门用于结束循环的,用于结束一个方法。当一个方法执行到一个return语句时,这个方法将被结束。与break和continue不同的是,return直接结束整个方法,不管这个return处于多少层循环之内
1 2 3 4
| public int calculateSum(int a, int b) { int sum = a + b; return sum; }
|
数组
Java中的数组是用于存储一组相同类型元素的数据结构。数组在Java中是一个固定长度的对象,可以存储基本数据类型(如int、char等)或对象引用。
一维数组
创建一维数组
(1)创建一维数组语法
1 2 3 4 5 6
| 数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,元素n};
数据类型[] 数组名 = new 数据类型[数组长度];
数据类型[] 数组名 = {元素1,元素2,元素3,元素n};
|
(2)创建一维数组例子
1 2 3 4 5 6 7 8 9 10 11 12
|
public class Demo { public static void main(String[] args) { int[] array1 = new int[]{1, 2, 3}; int[] array2 = {1, 2, 3}; String[] array3 = new String[3]; array3[0] = "A"; array3[1] = "B"; array3[2] = "C"; } }
|
一维数组的访问
数组中的元素是通过索引访问的,索引从0开始
1 2 3 4 5 6 7 8 9 10 11
|
public class Demo { public static void main(String[] args) { int[] array = {1, 2, 3}; System.out.println(array.length); System.out.println(array[0]); System.out.println(array[1]); System.out.println(array[2]); } }
|
一维数组的遍历
1 2 3 4 5 6 7 8 9 10
|
public class Demo { public static void main(String[] args) { int[] array = {1, 2, 3}; for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } }
|
案例:生成随机长度为10的两位数数组,并遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
public class Demo { @Test public int[] randomArray() { int[] array = new int[10]; for (int i = 0; i < array.length; i++) { array[i] = (int) (Math.random() * (99 - 10 + 1) + 10); } for (int i = 0; i < array.length; i++) { System.out.print(array[i] + " "); } return array; } }
|
二维数组(多维数组)
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组
创建二维数组
(1)创建二维数组语法
1 2 3 4 5 6
| 数据类型[][] 数组名称 = new 数据类型 [行数][列数] { {元素1,元素2,元素n},{元素1,元素2,元素n} };
数据类型[][] 数组名称 = new 数据类型 [行数][列数];
数据类型[][] 数组名称 = { {元素1,元素2,元素n},{元素1,元素2,元素n} }
|
(2)创建二维数组例子
1 2 3 4 5 6 7 8 9 10 11
|
public class Demo { public static void main(String[] args) { int[][] array1 = new int[][]{{1, 2, 3}, {4, 5, 6}}; int[][] array3 = {{1, 2, 3}, {4, 5, 6}}; int[][] array2 = new int[3][2]; array2[0] = new int[]{1, 2, 3}; array2[1] = new int[]{4, 5, 6}; } }
|
二维数组的访问
1 2 3 4 5 6 7 8 9 10 11 12 13
|
public class Demo { public static void main(String[] args) { int[][] array = {{1, 2, 3}, {4, 5, 6}}; System.out.println(array[0][0]); System.out.println(array[0][1]); System.out.println(array[0][2]); System.out.println(array[1][0]); System.out.println(array[1][1]); System.out.println(array[1][2]); } }
|
二维数组的遍历
1 2 3 4 5 6 7 8 9 10 11 12 13
|
public class Demo { public static void main(String[] args) { int[][] array = {{1, 2, 3}, {4, 5, 6}}; for (int i = 0; i < array.length; i++) { for (int j = 0; j < array[i].length; j++) { System.out.print(array[i][j] + " "); } System.out.println(); } } }
|
数组涉及的常见算法
| 常见算法 | 简介 |
|---|
| 数组元素的赋值 | 杨辉三角、回形数等 |
| 数组的各种求值 | 最大值、最小值、平均数、总和等 |
| 数组的复制、反转、查找 | 线性查找、二分法查找 |
| 数组元素的排序算法 | 选择排序(直接选择排序、堆排序)、交换排序(冒泡排序、快速排序) 插入排序(直接插入排序、折半插入排序、Shell排序)、归并排序 、桶式排序、基数排序 |
赋值
杨辉三角
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
| public class Demo {
@Test public void test5() { int array[][] = new int[10][];
for (int i = 0; i < array.length; i++) { array[i] = new int[i + 1]; array[i][0] = array[i][i] = 1; if (i > 1) { for (int j = 1; j < array[i].length - 1; j++) { array[i][j] = array[i - 1][j - 1] + array[i - 1][j];
} }
}
for (int i = 0; i < array.length; i++) { for (int j = 0; j < array[i].length; j++) { System.out.print(array[i][j] + " "); } System.out.println(); } } }
|
回形数
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
| public class Demo { public static void main(String[] args) { while (true) { Scanner scanner = new Scanner(System.in); System.out.println("请输入回型数大小数值:"); int n = scanner.nextInt(); int[][] arr = new int[n][n];
int count = 0; int maxX = n - 1; int maxY = n - 1; int minX = 0; int minY = 0;
while (minX <= maxX) { for (int x = minX; x <= maxX; x++) { arr[minY][x] = ++count; } minY++; for (int y = minY; y <= maxY; y++) { arr[y][maxX] = ++count; } maxX--; for (int x = maxX; x >= minX; x--) { arr[maxY][x] = ++count; } maxY--; for (int y = maxY; y >= minY; y--) { arr[y][minX] = ++count; } minX++; System.out.println(count); } for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr[i].length; j++) { System.out.print(arr[i][j] + " "); } System.out.println(); } return; } } }
|
求值
求和
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Demo { @Test public void test() { int[][] are = new int[][]{{1, 2}, {3, 4}, {5, 6}}; int sum = 0; for (int i = 0; i < are.length; i++) { for (int j = 0; j < are[i].length; j++) { sum += are[i][j]; } } System.out.println("总和为:" + sum); } }
|
最大值
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Demo { @Test public void max(){ int[] array = {1, 2, 3}; int max = array[0]; for (int i = 1; i < array.length; i++) { if (max < array[i]) { max = array[i]; } } System.out.println("最大数:" + max); } }
|
最小值
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Demo { @Test public void min() { int[] array = {1, 2, 3}; int min = array[0]; for (int i = 1; i < array.length; i++) { if (min > array[i]) { min = array[i]; } } System.out.println("最小数:" + min); } }
|
求和
1 2 3 4 5 6 7 8 9 10 11
| public class 求和 { @Test public void sum() { int[] array = {1, 2, 3}; int sumNum = 0; for (int i = 0; i < array.length; i++) { sumNum += array[i]; } System.out.println(sumNum); } }
|
平均值
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class 平均值 { @Test public void avg(){ int[] array = {1, 2, 3}; int sumNum = 0; for (int i = 0; i < array.length; i++) { sumNum += array[i]; } int avg = sumNum / array.length; System.out.println("平均值:" + avg); } }
|
复制、反转、查找
复制
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 Demo { @Test public void copy() { int[] arr1,arr2; arr1=new int[] {1,2,3,4,5}; System.out.println("arr1中元素:"); for(int i=0;i<arr1.length;i++) { System.out.print(arr1[i]+" "); } System.out.println(); arr2=new int[arr1.length]; for(int i=0;i<arr2.length;i++) { arr2[i]=arr1[i]; } System.out.println("arr2中元素:"); for(int i=0;i<arr2.length;i++) { System.out.print(arr2[i]+" "); } System.out.println(); } }
|
反转
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
| public class Demo { @Test public void reverse1() { int[] array = new int[]{1, 2, 3, 4, 5};
for (int i = 0; i < array.length / 2; i++) { int reverse = array[i]; array[i] = array[array.length - i - 1]; array[array.length - i - 1] = reverse; } System.out.println("反转后:"); for (int i = 0; i < array.length; i++) { System.out.print(array[i] + " "); }
}
@Test public void reverse2(){ int[] array = new int[]{1, 2, 3, 4, 5}; for (int i = 0, j = array.length - 1; i < j; i++, j--) { int reverse = array[i]; array[i] = array[j]; array[j] = reverse; } System.out.println("反转后:"); for (int i = 0; i < array.length; i++) { System.out.print(array[i] + " "); } } }
|
线性查找
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class Demo { @Test public void chazhao() { System.out.println("数组的查找(线性)"); String[] array = new String[]{"a", "b", "c", "d", "e"}; String chazhao = "b"; boolean isFlag = true; for (int i = 0; i < array.length; i++) { if (chazhao.equals(array[i])) { System.out.println("找到了指定元素,位置为:" + i); isFlag = false; break; } } if (isFlag) { System.out.println("没找到"); } } }
|
二分法查找
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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
public class 二分法查找 { static int count;
public static void main(String[] args) { int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
System.out.println(searchRecursive(array, 0, array.length - 1, 9)); System.out.println(count); count = 0; System.out.println(searchLoop(array, 9)); System.out.println(count); }
public static int searchRecursive(int[] array, int start, int end, int findValue) { if (array == null) { return -1; } count++; if (start <= end) { int middle = (start + end) / 1; int middleValue = array[middle];
if (findValue == middleValue) { return middle; } else if (findValue < middleValue) { return searchRecursive(array, start, middle - 1, findValue); } else { return searchRecursive(array, middle + 1, end, findValue); } } else { return -1; } }
public static int searchLoop(int[] array, int findValue) { if (array == null) { return -1; }
int start = 0; int end = array.length - 1;
while (start <= end) { count++; int middle = (start + end) / 2; int middleValue = array[middle];
if (findValue == middleValue) { return middle; } else if (findValue < middleValue) { end = middle - 1; } else { start = middle + 1; } } return -1; } }
|
排序
冒泡排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class Demo { @Test public void maopao() { int[] arr = new int[]{20, 30, -40, 80, 60, -50, 10};
for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr.length - 1 - i; j++) { if (arr[j] > arr[j + 1]) { int zhuan = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = zhuan; } } } for (int i = 0; i < arr.length; i++) { System.out.print(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 28 29 30 31 32 33 34 35 36 37 38 39
| public class Demo { private static void swap(int[] data, int i, int j) { int temp = data[i]; data[i] = data[j]; data[j] = temp; }
private static void subSort(int[] data, int start, int end) { if (start < end) { int base = data[start]; int low = start; int high = end + 1; while (true) { while (low < end && data[++low] - base <= 0) ; while (high > start && data[--high] - base >= 0) ; if (low < high) { swap(data, low, high); } else { break; } } swap(data, start, high); subSort(data, start, high - 1); subSort(data, high + 1, end); } }
public static void quickSort(int[] data) { subSort(data, 0, data.length - 1); }
public static void main(String[] args) { int[] data = {9, -16, 30, 0, 23, -30, -49, 25, 21, 30}; System.out.println("排序之前:" + java.util.Arrays.toString(data)); quickSort(data); System.out.println("排序之后:" + java.util.Arrays.toString(data)); } }
|
数组工具类
自定义数组工具类
为了方便操作数组,我们可以把操作逻辑进行封装
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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
public class MyArraysUtils {
public int getmax(int[] arr) { int fmax = arr[0]; for (int i = 0; i < arr.length; i++) { if (fmax < arr[i]) { fmax = arr[i]; } } return fmax; }
public int getmin(int[] arr) { int fmin = arr[0]; for (int i = 0; i < arr.length; i++) { if (fmin > arr[i]) { fmin = arr[i]; } } return fmin; }
public int gethe(int[] arr) { int he = 0; for (int i = 0; i < arr.length; i++) { he += arr[i]; } return he; }
public int getjun(int[] arr) {
return gethe(arr) / arr.length; }
public void getfan(int[] arr) { for (int i = 0; i < arr.length / 2; i++) { int zhuan = arr[i]; arr[i] = arr[arr.length - i - 1]; arr[arr.length - i - 1] = zhuan; } }
public int[] getfuzhi(int[] arr) {
int[] srr = new int[arr.length]; for (int i = 0; i < srr.length; i++) { srr[i] = arr[i]; } return srr;
}
public void getpai(int[] arr) { for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr.length - 1 - i; j++) { if (arr[j] > arr[j + 1]) { int zhuan = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = zhuan; } }
} for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } }
public void bianli(int[] arr) { for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } } }
|
Arrays工具类
java.util.Arrays是JDK提供的操作数组的工具类,提供许多操作数组的方法,而且这些方法都是静态的,所以在使用时不用创建对象,程序员直接调用就行
| 方法 | 介绍 |
|---|
| boolean equals(int[] a,int[] b) | 判断两个数组是否相等 |
| String toString(int[] a) | 输出数组信息 |
| void fill(int[] a,int val) | 将指定值填充到数组之中 |
| void sort(int[] a) | 对数组进行排序 |
| Int binarySearch(int[] a,int key) | 对排序后的数组进行二分法检索指定的值 |
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
| import org.junit.Test; import java.util.Arrays;
public class testArrays {
@Test public void testEquals() { int[] arr1 = new int[]{1, 2, 3}; int[] arr2 = new int[]{3, 2, 1}; boolean isEquals = Arrays.equals(arr1, arr2); System.out.println(isEquals); }
@Test public void testToString() { int[] arr = new int[]{1, 2, 3}; System.out.println(Arrays.toString(arr)); }
@Test public void testFill() { int[] arr = new int[]{1, 2, 3}; Arrays.fill(arr, 10); System.out.println(Arrays.toString(arr)); }
@Test public void testSort() { int[] arr = new int[]{3, 1, 2}; Arrays.sort(arr); System.out.println(Arrays.toString(arr)); }
@Test public void testBinarySearch() { int[] arr = new int[]{3, 2, 1, 4, 5}; int index = Arrays.binarySearch(arr, 5); if (index >= 0) { System.out.println(index); } else { System.out.println("未找到"); } }
}
|