目录
1. JAVA简介
1.1 主要特性
1.2 开发工具
2. JAVA环境配置
2.1 Windows系统安装JAVA
2.1.1 jdk下载
2.1.2 jdk安装及环境变量配置
2.2 Windows系统安装IntelliJ IDEA
2.2.1 下载安装Intelli IDEA
2.2.2 汉化
2.3 MacOS安装JAVA
2.3.1 jdk下载安装
2.4 MacOS安装IntelliJ IDEA
2.4.1 下载安装IntelliJ IDEA
3. JAVA零基础入门学习
3.1 使用 IntelliJ IDEA创建第一个 Java 应用
3.1.1 修饰符
3.1.1.1 访问修饰符
3.1.1.2 非访问修饰符
3.2 基本数据类型
3.2.1 内置数据类型
3.2.2 引用类型
3.3 常量与变量
3.3.1 常量
3.3.2 变量
3.3.2.1 局部变量
3.3.2.2 实例(成员)变量
3.3.2.3 静态变量
3.3.2.4 参数变量
3.4 类型转化
3.4.1 自动类型转换
3.4.2 强制类型转换
3.4.3 隐含强制类型转换
3.5 运算符号
3.5.1 算数运算符
3.5.2 关系运算符
3.5.3 位运算符
3.5.4 逻辑运算符
3.5.5 赋值运算符
3.5.6 三元(条件)运算符
3.6.7 对象实例运算符
3.6.8 运算符优先级
3.6 条件语句
3.6.1 if条件语句
3.6.2 switch..case条件语句
3.7 循环语句
3.7.1 while循环
3.7.2 do...while循环
3.7.3 for循环
3.7.3.1 基础for循环
3.7.3.2 for循环中使用break关键字
3.7.3.3 for循环中使用continue关键字
3.7.3.4 增强for循环
3.8 数组
3.8.1 一维数组
3.8.2 多维数组
3.8.3 Arrarys类
3.9 包装类
3.9.1 String类
3.9.1.1 创建字符串
3.9.1.2 字符串长度
3.9.1.3 连接字符串
3.9.1.4 格式化字符串
3.9.1.5 String方法
3.9.2 StringBuffer 和 StringBuilder 类
3.9.2.1 StringBuilder
3.9.2.2 StringBuffer
3.9.3 Character 类
3.9.4 Number & Math 类
3.9.4.1 Number类
3.9.4.2 Math类
3.9.4.3 Number &Math类方法
3.9.5 日期和时间
3.9.5.1 Date的创建和方法
3.9.5.2 日期格式化
3.9.5.3 Calendar类
3.9.5.4 GregorianCalendar类
3.9.6 Stream & File & IO
3.9.6.1 控制台输入/输出
3.9.6.2 读写文件
3.9.7 Scanner 类
3.9.8 正则表达式
4.0 方法
4.0.1 方法定义及调用
4.0.2 方法的重载
4.0.3 可变参数
4.0.4 构造方法
4.1 异常处理
4.1.1 Exception 类的层次
4.1.2 Java 内置异常类
4.1.3 异常方法
4.1.4 捕获异常
4.1.5 自定义异常
4.2 附录
1. JAVA简介
Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 面向对象程序设计语言和 Java 平台的总称。由 James Gosling和同事们共同研发,并在 1995 年正式推出。
后来 Sun 公司被 Oracle (甲骨文)公司收购,Java 也随之成为 Oracle 公司的产品。
Java分为三个体系:
JavaSE:Java Platform Standard Edition,java平台标准版JavaEE:Java Platform,Enterprise Edition,java平台企业版JavaME:Java Platform Micro Edition,java平台微型版1.1 主要特性
Java 语言是简单的:Java 语言的语法与 C 语言和 C++ 语言很接近,使得大多数程序员很容易学习和使用。另一方面,Java 丢弃了 C++ 中很少使用的、很难理解的、令人迷惑的那些特性,如操作符重载、多继承、自动的强制类型转换。特别地,Java 语言不使用指针,而是引用。并提供了自动分配和回收内存空间,使得程序员不必为内存管理而担忧。
Java 语言是面向对象的:Java 语言提供类、接口和继承等面向对象的特性,为了简单起见,只支持类之间的单继承,但支持接口之间的多继承,并支持类与接口之间的实现机制(关键字为 implements)。Java 语言全面支持动态绑定,而 C++语言只对虚函数使用动态绑定。总之,Java语言是一个纯的面向对象程序设计语言。
Java语言是分布式的:Java 语言支持 Internet 应用的开发,在基本的 Java 应用编程接口中有一个网络应用编程接口(java net),它提供了用于网络应用编程的类库,包括 URL、URLConnection、Socket、ServerSocket 等。Java 的 RMI(远程方法激活)机制也是开发分布式应用的重要手段。
Java 语言是健壮的:Java 的强类型机制、异常处理、垃圾的自动收集等是 Java 程序健壮性的重要保证。对指针的丢弃是 Java 的明智选择。Java 的安全检查机制使得 Java 更具健壮性。
Java语言是安全的:Java通常被用在网络环境中,为此,Java 提供了一个安全机制以防恶意代码的攻击。除了Java 语言具有的许多安全特性以外,Java 对通过网络下载的类具有一个安全防范机制(类 ClassLoader),如分配不同的名字空间以防替代本地的同名类、字节代码检查,并提供安全管理机制(类 SecurityManager)让 Java 应用设置安全哨兵。
Java 语言是体系结构中立的:Java 程序(后缀为 java 的文件)在 Java 平台上被编译为体系结构中立的字节码格式(后缀为 class 的文件),然后可以在实现这个 Java 平台的任何系统中运行。这种途径适合于异构的网络环境和软件的分发。
Java 语言是可移植的:这种可移植性来源于体系结构中立性,另外,Java 还严格规定了各个基本数据类型的长度。Java 系统本身也具有很强的可移植性,Java 编译器是用 Java 实现的,Java 的运行环境是用 ANSI C 实现的。
Java 语言是解释型的:如前所述,Java 程序在 Java 平台上被编译为字节码格式,然后可以在实现这个 Java 平台的任何系统中运行。在运行时,Java 平台中的 Java 解释器对这些字节码进行解释执行,执行过程中需要的类在联接阶段被载入到运行环境中。
Java 是高性能的:与那些解释型的高级脚本语言相比,Java 的确是高性能的。事实上,Java 的运行速度随着 JIT(Just-In-Time)编译器技术的发展越来越接近于 C++。
Java 语言是多线程的:在 Java 语言中,线程是一种特殊的对象,它必须由 Thread 类或其子(孙)类来创建。通常有两种方法来创建线程:其一,使用型构为 Thread(Runnable) 的构造子类将一个实现了 Runnable 接口的对象包装成一个线程,其二,从 Thread 类派生出子类并重写 run 方法,使用该子类创建的对象即为线程。值得注意的是 Thread 类已经实现了 Runnable 接口,因此,任何一个线程均有它的 run 方法,而 run 方法中包含了线程所要运行的代码。线程的活动由一组方法来控制。Java 语言支持多个线程的同时执行,并提供多线程之间的同步机制(关键字为 synchronized)。
Java 语言是动态的:Java 语言的设计目标之一是适应于动态变化的环境。Java 程序需要的类能够动态地被载入到运行环境,也可以通过网络来载入所需要的类。这也有利于软件的升级。另外,Java 中的类有一个运行时刻的表示,能进行运行时刻的类型检查。
1.2 开发工具
JAVA 开发工具
Linux 系统、Mac OS 系统、Windows 95/98/2000/XP,WIN 7/8系统。Java JDK 7、8……vscode 编辑器或者其他编辑器。IDE:Eclipse、 IntelliJ IDEA、NetBeans 等。开发工具中,IntelliJ IDEA,是Java编程语言的集成开发环境。IntelliJ在业界被公认为最好的Java开发工具,尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能可以说是超常的
2. JAVA环境配置
2.1 Windows系统安装JAVA
2.1.1 jdk下载
下载地址:Java Downloads | Oracle
2.1.2 jdk安装及环境变量配置
jdk环境变量配置
a.我的电脑——属性——高级系统设置——高级——环境变量
b.系统变量——新建 变量名为JAVA_HOME,变量值为JAVA JDK安装目录
c.系统变量——新建 变量名CLASSPATH,变量值 .;%JAVA_HOME%\lib
d.选择“系统变量”中变量名为“Path”的环境变量,双击该变量,在原来变量后追加 %JAVA_HOME%\bin
测试JDK环境变量的配置成功与否。在DOS命令行窗口输入“JAVAC”,输出帮助信息即为配置正确
Java -version查看版本号
2.2 Windows系统安装IntelliJ IDEA
2.2.1 下载安装Intelli IDEA
下载地址:Download IntelliJ IDEA – The Leading Java and Kotlin IDE
安装
2.2.2 汉化
File——Settings——Plugins,搜索Chinese ,安装 汉 Chinese(Simplified);安装后重启即可
2.3 MacOS安装JAVA
2.3.1 jdk下载安装
由于我本人的电脑是M1芯片,因此需要下载ARM64位的
下载地址:Java Downloads | Oracle
安装
使用java -version命令查看jdk版本
2.4 MacOS安装IntelliJ IDEA
2.4.1 下载安装IntelliJ IDEA
Download IntelliJ IDEA – The Leading Java and Kotlin IDE
汉化参照 2.2.3章节
3. JAVA零基础入门学习
3.1 使用 IntelliJ IDEA创建第一个 Java 应用
3.1.1 修饰符
3.1.1.1 访问修饰符
default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)public : 对所有类可见。使用对象:类、接口、变量、方法protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)protected特别说明:
子类与基类在同一包中:被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问子类与基类不在同一包中:那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的protected方法修饰符 | 当前类 | 同一包内 | 子孙类(同一包) | 子孙类(不同包) | 其他包 |
---|---|---|---|---|---|
public | Y | Y | Y | Y | Y |
protected | Y | Y | Y | Y/N | N |
default | Y | Y | Y | N | N |
private | Y | N | N | N | N |
访问控制和继承
请注意以下方法继承的规则:
3.1.1.2 非访问修饰符
static:静态变量或者静态方法
final:常量
abstract:
ransient:序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。该修饰符包含在定义变量的语句中,用来预处理类和变量的数据类型。
synchronized:synchronized 关键字声明的方法同一时间只能被一个线程访问。synchronized 修饰符可以应用于四个访问修饰符。
volatile:volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
一个 volatile 对象引用可能是 null。
3.2 基本数据类型
3.2.1 内置数据类型
Java语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。
类型 | 数据范围 | 默认值 | 说明 |
byte | (-2^7)~(2^7-1) | 0 | byte 数据类型是8位、有符号的,以二进制补码表示的整数;byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一 |
short | (-2^15)~(2^15 - 1)
| 0 | short 数据类型是 16 位、有符号的以二进制补码表示的整数;Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一 |
int | (-2^31)~(2^31 - 1) | 0 | int 数据类型是32位、有符号的以二进制补码表示的整数;一般地整型变量默认为 int 类型 |
long | (-2^63)~(2^63 -1) | 0L | long 数据类型是 64 位、有符号的以二进制补码表示的整数;这种类型主要使用在需要比较大整数的系统上 |
float |
| 0.0f | float 数据类型是单精度、32位、符合IEEE 754标准的浮点数;loat 在储存大型浮点数组的时候可节省内存空间;浮点数不能用来表示精确的值,如货币 |
double |
| 0.0d | double 数据类型是双精度、64 位、符合 IEEE 754 标准的浮点数;浮点数的默认类型为 double 类型;double类型不能表示精确的值,如货币; |
boolean |
| false | boolean数据类型表示一位的信息;只有两个取值:true 和 false;这种类型只作为一种标志来记录 true/false 情况 |
char | \u0000(十进制等效值为 0)~\uffff(即为 65535) | 'u0000' | char 类型是一个单一的 16 位 Unicode 字符;char 数据类型可以储存任何字符; |
对于数据类型的数据范围,我们无需强制记忆,因为他们都已经通过常量的方式定义在对应的包装类中了
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.public class Main { public static void main(String[] args) { // byte System.out.println("基本类型:byte 二进制位数:" + Byte.SIZE); System.out.println("byte 最小值:Byte.MIN_VALUE=" + Byte.MIN_VALUE); System.out.println("byte 最大值:Byte.MAX_VALUE=" + Byte.MAX_VALUE); //short System.out.println("基本类型:short 二进制位数:" + Short.SIZE); System.out.println("short 最小值:Short.MIN_VALUE=" + Short.MIN_VALUE); System.out.println("short 最大值:Short.MAX_VALUE=" + Short.MAX_VALUE); //int System.out.println("基本类型:int 二进制位数:" + Integer.SIZE); System.out.println("int 最小值:Int.MIN_VALUE=" + Integer.MIN_VALUE); System.out.println("int 最大值:Int.MAX_VALUE=" + Integer.MAX_VALUE); //long System.out.println("基本类型:long 二进制位数:" + Long.SIZE); System.out.println("long 最小值:Long.MIN_VALUE=" + Long.MIN_VALUE); System.out.println("long 最大值:Long.MAX_VALUE=" + Long.MAX_VALUE); //float System.out.println("基本类型:float 二进制位数:" + Float.SIZE); System.out.println("float 最小值:Float.MIN_VALUE=" + Float.MIN_VALUE); System.out.println("float 最大值:Float.MAX_VALUE=" + Float.MAX_VALUE); //double System.out.println("基本类型:double 二进制位数:" + Double.SIZE); System.out.println("double 最小值:Float.MIN_VALUE=" + Double.MIN_VALUE); System.out.println("double 最大值:Float.MAX_VALUE=" + Double.MAX_VALUE); //char System.out.println("基本类型:char 二进制位数:" + Character.SIZE); // 以数值形式而不是字符形式将Character.MIN_VALUE输出到控制台 System.out.println("char 最小值:Character.MIN_VALUE=" + (int) Character.MIN_VALUE); // 以数值形式而不是字符形式将Character.MAX_VALUE输出到控制台 System.out.println("char 最大值:Character.MAX_VALUE=" + (int) Character.MAX_VALUE); }}
默认值
public class Main { static boolean bool; static byte by; static char ch; static double d; static float f; static int i; static long l; static short sh; static String str; public static void main(String[] args) { System.out.println("Bool 默认值:" + bool); System.out.println("Byte 默认值:" + by); System.out.println("Character 默认值:" + (int)ch); System.out.println("Double 默认值:" + d); System.out.println("Float 默认值:" + f); System.out.println("Integer 默认值:" + i); System.out.println("Long 默认值:" + l); System.out.println("Short 默认值:" + sh); System.out.println("String 默认值:" + str); }}
3.2.2 引用类型
在Java中,引用类型的变量非常类似于C/C++的指针。引用类型指向一个对象,指向对象的变量是引用变量。这些变量在声明时被指定为一个特定的类型,比如 Employee、Puppy 等。
变量一旦声明后,类型就不能被改变了。对象、数组都是引用数据类型。所有引用类型的默认值都是null。一个引用变量可以用来引用任何与之兼容的类型。例子:Site site = new Site("Runoob")。3.3 常量与变量
3.3.1 常量
常量在程序运行时是不能被修改的在 Java 中使用 final 关键字来修饰常量,虽然常量名也可以用小写,但为了便于识别,通常使用大写字母表示常量public class Main { public static void main(String[] args) { //定义常量 final double PI=3.1415926; }}
字面量可以赋给任何内置类型的变量byte、int、long、和short都可以用十进制、16进制以及8进制的方式来表示,当使用字面量的时候,前缀 0 表示 8 进制,而前缀 0x 代表 16 进制字符串常量也是包含在两个引号之间的字符序列字符串常量和字符变量都可以包含任何 Unicode 字符 //TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.public class Main { public static void main(String[] args) { //字面量可以赋给任何内置类型的变量 byte a = 68; char b = 'A'; System.out.println(a); System.out.println((int)b); //byte、int、long、和short都可以用十进制、16进制以及8进制的方式来表示, // 当使用字面量的时候,前缀 0 表示 8 进制,而前缀 0x 代表 16 进制 int decimal = 100; int octal = 0144; //100 int hexa = 0x64; //100 System.out.println(decimal); System.out.println(octal); System.out.println(hexa); //字符串常量也是包含在两个引号之间的字符序列 String str1="hello word"; String str2="two\\lines"; String str3="\\\"This is in quotes\\\""; System.out.println(str1); System.out.println(str2); System.out.println(str3); //字符串常量和字符变量都可以包含任何 Unicode 字符 char ch = '\u0001'; String strA = "\u0001"; System.out.println((int)ch); System.out.println(strA); }}
特殊的转义字符序列
\n:换行\r:回车\f:换页\b:退格\0:空字符\s:空格\t:制表符\":双引号\\:反斜杠\ddd:八进制字符\uxxxx:16禁止Unicode字符3.3.2 变量
字所有的变量在使用前必须声明,声明变量的基本格式如下:
type identifier [ = value][, identifier [= value] ...] ;
格式说明:
type -- 数据类型identifier -- 是变量名,可以使用逗号 , 隔开来声明多个同类型变量public class Main { public static void main(String[] args) { int a, b, c; // 声明三个int型整数:a、 b、c int d = 3, e = 4, f = 5; // 声明三个整数并赋予初值 byte z = 22; // 声明并初始化 z String s = "runoob"; // 声明并初始化字符串 s double pi = 3.14159; // 声明了双精度浮点型变量 pi char x = 'x'; // 声明变量 x 的值是字符 'x'。 }}
命名规则:
使用有意义的名字: 变量名应该具有清晰的含义,能够准确地反映变量的用途。避免使用单个字符或无意义的缩写。驼峰命名法(Camel Case): 在变量名中使用驼峰命名法,即将每个单词的首字母大写,除了第一个单词外,其余单词的首字母都采用大写形式。例如:myVariableName。避免关键字: 不要使用 Java 关键字(例如,class、int、boolean等)作为变量名。区分大小写: Java 是大小写敏感的,因此变量名中的大小写字母被视为不同的符号。例如,myVariable 和 myvariable 是两个不同的变量。不以数字开头: 变量名不能以数字开头,但可以包含数字。遵循命名约定: 对于不同类型的变量(局部变量、实例变量、静态变量等),可以采用不同的命名约定,例如使用前缀或后缀来区分。3.3.2.1 局部变量
局部变量(Local Variables)是在方法、构造函数或块内部声明的变量,它们在声明的方法、构造函数或块执行结束后被销毁,局部变量在声明时需要初始化,否则会导致编译错误。其作用域限制在声明它的代码块内部。
声明语法:type variableName;
语法说明:
作用域:局部变量的作用域限于它被声明的方法、构造方法或代码块内。一旦代码执行流程离开这个作用域,局部变量就不再可访问。
生命周期:局部变量的生命周期从声明时开始,到方法、构造方法或代码块执行结束时终止。之后,局部变量将被垃圾回收。
初始化:局部变量在使用前必须被初始化。如果不进行初始化,编译器会报错,因为 Java 不会为局部变量提供默认值。
声明:局部变量的声明必须在方法或代码块的开始处进行。声明时可以指定数据类型,后面跟着变量名,例如:int count;。
赋值:局部变量在声明后必须被赋值,才能在方法内使用。赋值可以是直接赋值,也可以是通过方法调用或表达式。
限制:局部变量不能被类的其他方法直接访问,它们只为声明它们的方法或代码块所私有。
内存管理:局部变量存储在 Java 虚拟机(JVM)的栈上,与存储在堆上的实例变量或对象不同。
垃圾回收:由于局部变量的生命周期严格限于方法或代码块的执行,它们在方法或代码块执行完毕后不再被引用,因此JVM的垃圾回收器会自动回收它们占用的内存。
重用:局部变量的名称可以在不同的方法或代码块中重复使用,因为它们的作用域是局部的,不会引起命名冲突。
参数和返回值:方法的参数可以视为一种特殊的局部变量,它们在方法被调用时初始化,并在方法返回后生命周期结束。
实例
public class Main { public static void main(String[] args) { int a=10;//声明病初始化变量a int b;//声明变量b b=20;//初始化变量b System.out.println("局部变量a:"+a); System.out.println("局部变量b:"+b); ShowDogAge(); } /*显示小狗年龄*/ public static void ShowDogAge(){ int age = 0; age = age + 7; System.out.println("小狗的年龄是: " + age); }}
3.3.2.2 实例(成员)变量
实例变量(Instance Variables)是在类中声明,但在方法、构造函数或块之外,它们属于类的实例,每个类的实例都有自己的副本,如果不明确初始化,实例变量会被赋予默认值(数值类型为0,boolean类型为false,对象引用类型为null)。
声明语法为:accessModifier type variableName;
语法说明:
其他说明:
成员变量声明在一个类中,但在方法、构造方法和语句块之外。当一个对象被实例化之后,每个成员变量的值就跟着确定。成员变量在对象创建的时候创建,在对象被销毁的时候销毁。成员变量的值应该至少被一个方法、构造方法或者语句块引用,使得外部能够通过这些方式获取实例变量信息。成员变量可以声明在使用前或者使用后。访问修饰符可以修饰成员变量。成员变量对于类中的方法、构造方法或者语句块是可见的。一般情况下应该把成员变量设为私有。通过使用访问修饰符可以使成员变量对子类可见。成员变量具有默认值。数值型变量的默认值是0,布尔型变量的默认值是 false,引用类型变量的默认值是 null。变量的值可以在声明时指定,也可以在构造方法中指定;成员变量可以直接通过变量名访问。但在静态方法以及其他类中,就应该使用完全限定名:ObjectReference.VariableName实例
package my.java.study;public class HelloWorld { public String bjName="";//公有成员变量 private String linkTel="189XXXXXXXX";//私有成员变量 /* 显示我的个人信息*/ public String ShowMyInfo(){ int age=18;//声明并初始化年龄 String myName="王小明";//声明并初始化姓名 String homeAddress="常州市新北区藻江花园";//声明并初始化住址 float weight=50.5f;//体重 float height;//声明身高变量 height=165f;//身高初始化 return String.format("大家好,我是来自%s的%s,我今年%d岁了。我家住在%s,我的身高是%.0f厘米,体重是%.1f公斤,联系电话%s",bjName,myName,age,homeAddress,height,weight,linkTel ); }}
import my.java.study.HelloWorld;public class Main { public static void main(String[] args) { int a=10;//声明病初始化变量a int b;//声明变量b b=20;//初始化变量b System.out.println("局部变量a:"+a); System.out.println("局部变量b:"+b); //实例hello world HelloWorld hw=new HelloWorld(); hw.bjName="三年级二班"; System.out.println(hw.ShowMyInfo()); }}
3.3.2.3 静态变量
静态变量是指在类中定义的一个变量,它与类相关而不是与实例相关,即无论创建多少个类实例,静态变量在内存中只有一份拷贝,被所有实例共享。
静态变量在类加载时被初始化,而且只初始化一次
定义方式:使用 static 关键字修饰变量,通常也称为类变量
访问方式:可以通过类名来访问,也可以通过实例名来访问
生命周期:静态变量的生命周期与程序的生命周期一样长,即它们在类加载时被创建,在整个程序运行期间都存在,直到程序结束才会被销毁。因此,静态变量可以用来存储整个程序都需要使用的数据,如配置信息、全局变量等。
初始化时机:静态变量在类加载时被初始化,其初始化顺序与定义顺序有关。
访问修饰符:访问修饰符可以是 public、protected、private 或者默认的访问修饰符
线程安全性:静态变量在内存中只有一份拷贝,被所有实例共享。因此,如果一个线程修改了静态变量的值,那么其他线程在访问该静态变量时也会看到修改后的值。这可能会导致并发访问的问题,因为多个线程可能同时修改静态变量,导致不确定的结果或数据一致性问题。为了确保静态变量的线程安全性,需要采取适当的同步措施,如同步机制、原子类或 volatile 关键字,以便在多线程环境中正确地读取和修改静态变量的值。
使用场景:存储全局状态或配置信息、计数器或统计信息、缓存数据或共享资源、工具类的常量或方法、单例模式中的实例变量
实例
定义一个全局配置类
package my.java.study;public class AppConfig { public static String AppName=""; public static String AppVersion=""; public static String AppDescription=""; /* 静态方法*/ public static String GetAppInfo(){ return String.format("app名称%s,当前版本号%s,app介绍%s",AppName,AppVersion,AppDescription); }}
引用全局配置字段
import my.java.study.*;public class Main { public static void main(String[] args) { AppConfig.AppName="移动执法"; AppConfig.AppVersion="V1.0"; AppConfig.AppDescription="随时随地记录执法情况"; System.out.println(AppConfig.GetAppInfo()); }}
3.3.2.4 参数变量
参数变量(Parameters)是方法或构造函数声明中的变量,用于接收调用该方法或构造函数时传递的值,参数变量的作用域只限于方法内部。
在调用方法时,我们必须为参数变量传递值,这些值可以是常量、变量或表达式。
声明语法:
accessModifier returnType methodName(parameterType parameterName1, parameterType parameterName2, ...) {
// 方法体
}
语法说明:
方法参数变量的值传递方式:
值传递:在方法调用时,传递的是实际参数的值的副本。当参数变量被赋予新的值时,只会修改副本的值,不会影响原始值。Java 中的基本数据类型都采用值传递方式传递参数变量的值。引用传递:在方法调用时,传递的是实际参数的引用(即内存地址)。当参数变量被赋予新的值时,会修改原始值的内容。Java 中的对象类型采用引用传递方式传递参数变量的值。实例
public class Main { public static void main(String[] args) { CalSum(2,5); } public static void CalSum(int x,int y){ System.out.println("两数之和:"+(x+y)); }}
3.4 类型转化
3.4.1 自动类型转换
整型、实型(常量)、字符型数据可以混合运算。运算中,不同类型的数据先转化为同一类型,然后进行运算。转换从低级到高级。
低 ------------------------------------> 高
byte,short,char—> int —> long—> float —> double
数据类型转换必须满足如下规则:
不能对boolean类型进行类型转换。不能把对象类型转换成不相关类的对象。在把容量大的类型转换为容量小的类型时必须使用强制类型转换。转换过程中可能导致溢出或损失精度,例如://因为 byte 类型是 8 位,最大值为127,所以当 int 强制转换为 byte 类型时,值 128 时候就会导致溢出。
int i =128;
byte b = (byte)i;
5.浮点数到整数的转换是通过舍弃小数得到,而不是四舍五入,例如:
(int)23.7 == 23;
(int)-45.89f == -45
实例
public class Main { public static void main(String[] args) { char c1='A';//定义一个 char int a=c1;//char 自动转换int System.out.println("char自动类型转换为int后的值等于"+a); int a1=c1+3;//char类型和int 类型计算 System.out.println("char类型和int计算后的值等于"+a1); }}
3.4.2 强制类型转换
public class Main { public static void main(String[] args) { /* * 1. 条件是转换的数据类型必须是兼容的。 * 2. 格式:(type)value type是要强制类型转换后的数据类型 */ int a=120; byte by1=(byte)a; System.out.println("int类型强制转换为byte后的值等于"+by1); }}
3.4.3 隐含强制类型转换
整数的默认类型是 int。小数默认是 double 类型浮点型,在定义 float 类型时必须在数字后面跟上 F 或者 f。3.5 运算符号
3.5.1 算数运算符
操作符 | 描述 |
+ | 加法 - 相加运算符两侧的值 |
- | 减法 - 左操作数减去右操作数 |
* | 乘法 - 相乘操作符两侧的值 |
/ | 除法 - 左操作数除以右操作数 |
% | 取余 - 左操作数除以右操作数的余数 |
++ | 自增: 操作数的值增加1 |
-- | 自减: 操作数的值减少1 |
实例
public class Main { public static void main(String[] args) { int a=10; int b=30; int c=40; int d=50; System.out.println("a加b的和是:"+(a+b)); System.out.println("c减b的差是:"+(c-b)); System.out.println("c乘以d的值是:"+(c*d)); System.out.println("d除以a的值是:"+(d/a)); System.out.println("d除以c的值是:"+(d/c)); System.out.println("d和b取余的值是:"+(d%b)); //注意区分左自增/自减和右自增/自减输出值的差别 System.out.println("a右自增值是:"+(a++)); System.out.println("a左自增值是:"+(++a)); System.out.println("d右自减值是:"+(d--)); System.out.println("d左自减值是:"+(--d)); }}
3.5.2 关系运算符
运算符 | 描述 |
== | 检查如果两个操作数的值是否相等,如果相等则条件为真。 |
!= | 检查如果两个操作数的值是否相等,如果值不相等则条件为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是那么条件为真。 |
< | 检查左操作数的值是否小于右操作数的值,如果是那么条件为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。 |
实例
public class Main { public static void main(String[] args) { int a = 10; int b = 20; System.out.println("a == b = " + (a == b) ); System.out.println("a != b = " + (a != b) ); System.out.println("a > b = " + (a > b) ); System.out.println("a < b = " + (a < b) ); System.out.println("b >= a = " + (b >= a) ); System.out.println("b <= a = " + (b <= a) ); }}
3.5.3 位运算符
操作符 | 描述 |
& | 如果相对应位都是1,则结果为1,否则为0 |
| | 如果相对应位都是 0,则结果为 0,否则为 1 |
^ | 如果相对应位值相同,则结果为0,否则为1 |
〜 | 按位取反运算符翻转操作数的每一位,即0变成1,1变成0。 |
<< | 按位左移运算符。左操作数按位左移右操作数指定的位数。 |
>> | 按位右移运算符。左操作数按位右移右操作数指定的位数。 |
>>> | 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。 |
实例
public class Main { public static void main(String[] args) { int a = 60; /* 60 = 0011 1100 */ int b = 13; /* 13 = 0000 1101 */ int c = 0; c = a & b; /* 12 = 0000 1100 */ System.out.println("a & b = " + c ); c = a | b; /* 61 = 0011 1101 */ System.out.println("a | b = " + c ); c = a ^ b; /* 49 = 0011 0001 */ System.out.println("a ^ b = " + c ); c = ~a; /*-61 = 1100 0011 */ System.out.println("~a = " + c ); c = a << 2; /* 240 = 1111 0000 */ System.out.println("a << 2 = " + c ); c = a >> 2; /* 15 = 1111 */ System.out.println("a >> 2 = " + c ); c = a >>> 2; /* 15 = 0000 1111 */ System.out.println("a >>> 2 = " + c ); }}
3.5.4 逻辑运算符
操作符 | 描述 |
&& | 称为逻辑与运算符。当且仅当两个操作数都为真,条件才为真。 |
| | | 称为逻辑或操作符。如果任何两个操作数任何一个为真,条件为真。 |
! | 称为逻辑非运算符。用来反转操作数的逻辑状态。如果条件为true, 则逻辑非运算符将得到false。 |
实例
public class Main { public static void main(String[] args) { int a = 60; int b = 13; System.out.println("a和b都大于10:"+(a>10&&b>10)); System.out.println("a或b都大于50:"+(a>50||b>50)); System.out.println("a<b是假的:"+!(a<b)); }}
3.5.5 赋值运算符
操作符 | 描述 |
= | 简单的赋值运算符,将右操作数的值赋给左侧操作数 |
+ = | 加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数 |
- = | 减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数 |
* = | 乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数 |
/ = | 除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数 |
(%)= | 取模和赋值操作符,它把左操作数和右操作数取模后赋值给左操作数 |
<< = | 左移位赋值运算符 |
>> = | 右移位赋值运算符 |
&= | 按位与赋值运算符 |
^ = | 按位异或赋值操作符 |
| = | 按位或赋值操作符 |
实例
public class Main { public static void main(String[] args) { int a = 10; int b = 20; int c = 0; c = a + b; System.out.println("c = a + b = " + c ); c += a ;//等价于c=c+a; System.out.println("c += a = " + c ); c -= a ;//等价于c=c-a; System.out.println("c -= a = " + c ); c *= a ;//等价于 c=c*a; System.out.println("c *= a = " + c ); a = 10; c = 15; c /= a ;//等价于 c=c/a; System.out.println("c /= a = " + c ); a = 10; c = 15; c %= a ;//等价于c=c%a; System.out.println("c %= a = " + c ); c <<= 2 ;//等价于 c=c<<2; System.out.println("c <<= 2 = " + c ); c >>= 2 ;//等价于 c=c>>2; System.out.println("c >>= 2 = " + c ); c &= a ;//等价于 c=c&a; System.out.println("c &= a = " + c ); c ^= a ;//等价于 c=c^a; System.out.println("c ^= a = " + c ); c |= a ;//等价于c=c|a; System.out.println("c |= a = " + c ); }}
3.5.6 三元(条件)运算符
表达式:
variable x = (expression) ? value if true : value if false
实例
public class Main { public static void main(String[] args) { int a,b; a=10; b=(a>10)?20:30; System.out.println("如果a大于10,那么b等于20,否则b等于30:"+b); }}
3.6.7 对象实例运算符
instanceof用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型)。
instanceof运算符使用格式如下:
( Object reference variable ) instanceof (class/interface type)
实例
public class Main { public static void main(String[] args) { String name = "James"; System.out.println("name是String型:"+(name instanceof String)); }}
3.6.8 运算符优先级
类别 | 操作符 | 关联性 |
后缀 | () [] . (点操作符) | 左到右 |
一元 | expr++ expr-- | 从左到右 |
一元 | ++expr --expr + - ~ ! | 从右到左 |
乘性 | * /% | 左到右 |
加性 | + - | 左到右 |
移位 | >> >>> << | 左到右 |
关系 | > >= < <= | 左到右 |
相等 | == != | 左到右 |
按位与 | & | 左到右 |
按位异或 | ^ | 左到右 |
按位或 | | | 左到右 |
逻辑与 | && | 左到右 |
逻辑或 | | | | 左到右 |
条件 | ?: | 从右到左 |
赋值 | = + = - = * = / =%= >> = << =&= ^ = | = | 从右到左 |
逗号 | , | 左到右 |
3.6 条件语句
条件语句允许程序根据条件的不同执行不同的代码块
3.6.1 if条件语句
单个if语句:
if(布尔表达式)
{
//如果布尔表达式为true将执行的语句
}
if..else语句:
if(布尔表达式){
//如果布尔表达式的值为true
}else{
//如果布尔表达式的值为false
}
if...else if...else语句:
if(布尔表达式 1){
//如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){
//如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){
//如果布尔表达式 3的值为true执行代码
}else {
//如果以上布尔表达式都不为true执行代码
}
嵌套的if...else语句:
if(布尔表达式 1){
如果布尔表达式 1的值为true执行代码
if(布尔表达式 2){
如果布尔表达式 2的值为true执行代码
}
}
实例
public class Main { public static void main(String[] args) { int a=10; int b=20; int c; //if语句 if(a<=10){ c=a+b; System.out.println("c等于a+b:"+c); } //if...else 语句 if(a<b){ c=b-a; } else{ c=a-b; } System.out.println("c的值:"+c); //if...else if...esle 语句 if(a>10){ c=a; } else if (a<=10) { c=a+b; } else{ c=a*b; } System.out.println("c的值:"+c); //嵌套的if...else 语句 if(a>=10){ if(a==10){ c=b; } else { c=a+b; } } System.out.println("c的值:"+c); }}
3.6.2 switch..case条件语句
switch case 语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。
语法格式:
switch(expression){
case value :
//语句
break; //可选
case value :
//语句
break; //可选
//你可以有任意数量的case语句
default : //可选
//语句
}
语法规则:
switch 语句中的变量类型可以是: byte、short、int、 char、String,同时 case 标签必须为字符串常量或字面量。switch 语句可以拥有多个 case 语句,每个 case 后面跟一个要比较的值和冒号。case 语句中的值的数据类型必须与变量的数据类型相同,而且只能是常量或者字面常量。当变量的值与 case 语句的值相等时,那么 case 语句之后的语句开始执行,直到 break 语句出现才会跳出 switch 语句。当遇到 break 语句时,switch 语句终止。程序跳转到 switch 语句后面的语句执行。case 语句不必须要包含 break 语句。如果没有 break 语句出现,程序会继续执行下一条 case 语句,直到出现 break 语句。switch 语句可以包含一个 default 分支,该分支一般是 switch 语句的最后一个分支(可以在任何位置,但建议在最后一个)。default 在没有 case 语句的值和变量值相等的时候执行。default 分支不需要 break 语句。实例
public class Main { public static void main(String[] args) { int userType=1; String userTypeDesc="医生"; switch (userType) { case 1: userTypeDesc="医生"; break; case 2: userTypeDesc="教师"; break; case 3: userTypeDesc="律师"; break; default: userTypeDesc="未知"; } System.out.println("人员类别:"+userTypeDesc); }}
3.7 循环语句
如果您想要同样的操作执行多次,就需要使用循环结构
3.7.1 while循环
语法结构:
while( 布尔表达式 ) {
//循环内容
}
只要布尔表达式为 true,循环就会一直执行下去
实例
public class Main { public static void main(String[] args) { int x = 10; while( x < 20 ) { System.out.println("value of x : " + x ); x++; } }}
3.7.2 do...while循环
对于 while 语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。
do…while 循环和 while 循环相似,不同的是,do…while 循环至少会执行一次。
语法结构:
do {
//代码语句
}while(布尔表达式);
注意:布尔表达式在循环体的后面,所以语句块在检测布尔表达式之前已经执行了。 如果布尔表达式的值为 true,则语句块一直执行,直到布尔表达式的值为 false。
实例
public class Main { public static void main(String[] args) { int x = 10; do{ System.out.println("value of x : " + x ); x++; }while( x < 20 ); }}
3.7.3 for循环
3.7.3.1 基础for循环
语法结构:
for(初始化; 布尔表达式; 更新) {
//代码语句
}
注意说明:
最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。然后,检测布尔表达式的值。如果为 true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。执行一次循环后,更新循环控制变量。再次检测布尔表达式。循环执行上面的过程。实例
public class Main { public static void main(String[] args) { for(int i=1;i<=10;i++){ System.out.println("Value of i:"+i); } }}
3.7.3.2 for循环中使用break关键字
for循环中使用break关键字跳出循环,终止整个循环
实例
public class Main { public static void main(String[] args) { for(int i=1;i<=10;i++){ //i等于5时,跳出循环 if(i==5){ break; } System.out.println("Value of i:"+i); } }}
3.7.3.3 for循环中使用continue关键字
在 for 循环中,continue 语句使程序跳出当前循环,继续下一个循环
实例
public class Main { public static void main(String[] args) { for(int i=1;i<=10;i++){ //i等于5时,跳出循环 if(i==5){ continue; } System.out.println("Value of i:"+i); } }}
3.7.3.4 增强for循环
增强型for循环主要用于数组
语法结构:
for(声明语句 : 表达式)
{
//代码句子
}
实例
public class Main { public static void main(String[] args) { //int 数组循环 int [] numbers = {10, 20, 30, 40, 50}; for(int x : numbers ){ System.out.println("Value of x:"+x ); } //字符串数组循环 String [] names={"Jack","Rose","WeiEr","Lisa"}; for(String n: names ){ System.out.println("Name:"+n); } }}
3.8 数组
数组是用来存储固定大小的同类型元素
3.8.1 一维数组
声明数组语法:
方式1:dataType[] arrayRefVar; // 首选的方法
方式2:dataType arrayRefVar[]; // 效果相同,但不是首选方法
创建数组语法:
arrayRefVar = new dataType[arraySize];//arraySize指的是需要创建数组的元素数量
数组和创建数组一条语句完成:
方式1:dataType[] arrayRefVar = new dataType[arraySize];//先初始化,指定数组大小
方式2:dataType[] arrayRefVar = {value0, value1, ..., valuek};//直接给数组赋值
实例
import java.util.Arrays;public class Main { public static void main(String[] args) { /* 先声明数组,再创建数组,再为数组赋值 * */ String []names;//声明姓名数组 names=new String[5];//创建姓名数组 //为姓名数组赋值 names[0]="Jack"; names[1]="John"; names[2]="Jane"; names[3]="Rose"; names[4]="Bob"; /*不允许超出数组的元素个数,否则报错*/ //names[5]="Weier";// System.out.println("姓名数组的元素个数:"+names.length); System.out.println("姓名数组的元素内容:"+String.join(",",names)); /*先创建10个元素的数字数组,再赋值*/ int [] numbers=new int[10];//创建 10个元素的数字数组 for(int i=1;i<=10;i++){ numbers[i-1]=i; } System.out.println("数字数组的元素内容:"+String.join(",", Arrays.toString(numbers))); /*直接创建并给数组赋值*/ String []classNames={"三年级1班","三年级2班","三年级3班"}; System.out.println("班级数组的元素个数:"+classNames.length); System.out.println("班级数组的元素内容:"+String.join(",",classNames)); /*使用Arrays.copyOf()方法:该方法可以复制原始数组,指定新的长度,并返回新的数组。*/ int []newNumbers=Arrays.copyOf(numbers,numbers.length+1); newNumbers[newNumbers.length-1]=11; System.out.println("新数字数组的元素内容:"+String.join(",", Arrays.toString(newNumbers))); /*使用System.arraycopy()方法:该方法可以将一个数组的指定范围内的元素复制到另一个数组中,并可以指定复制后的起始位置。*/ String[] newNames = new String[names.length + 1]; // 创建新数组,并指定新的长度 System.arraycopy(names, 0, newNames, 0, names.length); // 复制原始数组的元素到新数组 newNames[newNames.length - 1] ="MeiGu"; // 添加元素到新数组的最后一个位置 System.out.println("新姓名数组的元素内容:"+String.join(",",newNames)); //for 循环数组 for(int i=0;i<names.length;i++){ System.out.println("姓名数组for循环,第"+(i+1)+"元素值:"+names[i]); } //for-each循环 for(int x:numbers){ System.out.println("数字数组for-eatch循环:"+x); } }}
3.8.2 多维数组
多维数组可以看成是数组的数组,以二维数组为例:
二维数组创建语法:
type[][] typeName = new type[typeLength1][typeLength2];
实例
import java.util.Arrays;public class Main { public static void main(String[] args) { //二维数组numbers 可以看成是一个两行三列的数组 int [] [] numbers=new int[2][3]; numbers[0][0]=1; numbers[0][1]=2; numbers[0][2]=3; numbers[1][0]=3; numbers[1][1]=4; numbers[1][2]=5; //循环数组内容 for(int[] xArr:numbers){ System.out.println("二维数组numbers的内容:"+Arrays.toString(xArr)); } //创建每行列不一样的二维数组 String [][] classNames=new String[2][]; classNames[0]=new String[3]; classNames[1]=new String[2]; classNames[0][0]="一年级1班"; classNames[0][1]="一年级2班"; classNames[0][2]="一年级3班"; classNames[1][0]="二年级1班"; classNames[1][1]="二年级2班"; //循环数组内容 for(String[] xArr:classNames){ System.out.println("二维数组classNames的内容:"+Arrays.toString(xArr)); } }}
输出结果:
3.8.3 Arrarys类
java.util.Arrays 类能方便地操作数组,它提供的所有方法都是静态的。
具有以下功能:
给数组赋值:通过 fill 方法。
对数组排序:通过 sort 方法,按升序。
比较数组:通过 equals 方法比较数组中元素值是否相等。
查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作。
方法 | 说明 |
public static int binarySearch(Object[] a, Object key) | 用二分查找算法在给定数组中搜索给定值的对象(Byte,Int,double等)。数组在调用前必须排序好的。如果查找值包含在数组中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。 |
public static boolean equals(long[] a, long[] a2) | 如果两个指定的 long 型数组彼此相等,则返回 true。如果两个数组包含相同数量的元素,并且两个数组中的所有相应元素对都是相等的,则认为这两个数组是相等的。换句话说,如果两个数组以相同顺序包含相同的元素,则两个数组是相等的。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。 |
public static void fill(int[] a, int val) | 将指定的 int 值分配给指定 int 型数组指定范围中的每个元素。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。 |
public static void sort(Object[] a) | 对指定对象数组根据其元素的自然顺序进行升序排列。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。 |
实例
import java.util.ArrayList;import java.util.Arrays;public class Main { public static void main(String[] args) { /*binarySearch*/ //无序字符串数组 ArrayList<String> names = new ArrayList<>(); names.add("John"); names.add("Jane"); names.add("Bob"); names.add("Mary"); System.out.println("names元素数量:"+names.toArray().length); //字符串数组 binarySearch:查找姓名为Bob的索引位置 int bobIndex=Arrays.binarySearch(names.toArray(),"Bob"); System.out.println("Bob所在的索引位置:"+bobIndex);//-1 int roseIndex=Arrays.binarySearch(names.toArray(),"Rose"); System.out.println("Rose所在的索引位置:"+roseIndex);//-5 //有序字符串数组 ArrayList<String> names3 = new ArrayList<>(); names3.add("A1"); names3.add("B1"); names3.add("C1"); names3.add("D1"); //字符串数组 binarySearch:查找姓名为Bob的索引位置 int bobIndex=Arrays.binarySearch(names3.toArray(),"A1"); System.out.println("A1所在的索引位置:"+bobIndex);//0 int roseIndex=Arrays.binarySearch(names3.toArray(),"E1"); System.out.println("E1所在的索引位置:"+roseIndex);//-5 //有序整数数组 ArrayList<Integer> numbers=new ArrayList<Integer>(); numbers.add(1); numbers.add(2); numbers.add(3); numbers.add(4); numbers.add(5); //numbers 有序数组查询 int fiveIndex=Arrays.binarySearch(numbers.toArray(),5); System.out.println("数字5所在的索引位置:"+fiveIndex);//4 int sixIndex=Arrays.binarySearch(numbers.toArray(),6); System.out.println("数字6所在的索引位置:"+sixIndex);//-6 //无序整数数组 ArrayList<Integer> numbers1=new ArrayList<Integer>(); numbers1.add(10); numbers1.add(7); numbers1.add(8); numbers1.add(9); numbers1.add(6); //numbers 无序数组查询 int nineIndex=Arrays.binarySearch(numbers1.toArray(),9); System.out.println("数字9所在的索引位置:"+nineIndex);//3 }}
import java.util.ArrayList;import java.util.Arrays;public class Main { public static void main(String[] args) { /*equal*/ //字符串数组 ArrayList<String> names = new ArrayList<>(); names.add("John"); names.add("Jane"); names.add("Bob"); names.add("Mary"); //元素顺序内容相同的两个数组相等比较 ArrayList<String> names1 = new ArrayList<>(); names1.add("John"); names1.add("Jane"); names1.add("Bob"); names1.add("Mary"); System.out.println("names1等于names:"+Arrays.equals(names1.toArray(),names.toArray())); //元素内容相同,但是元素顺序不同的两个数组相等判断 ArrayList<String> names2 = new ArrayList<>(); names2.add("Mary"); names2.add("John"); names2.add("Jane"); names2.add("Bob"); System.out.println("names2等于names:"+Arrays.equals(names2.toArray(),names.toArray())); }}
import java.util.ArrayList;import java.util.Arrays;public class Main { public static void main(String[] args) { /*fill*/ ArrayList<String> names = new ArrayList<>(); names.add("John"); names.add("Jane"); names.add("Bob"); names.add("Mary"); //未指定替换元素,默认替换所有元素 var names1=names.toArray(); System.out.println("fill前的数组内容:"+Arrays.toString(names1));//[John, Jane, Bob, Mary] Arrays.fill(names1,"1"); System.out.println("fill后的数组内容:"+Arrays.toString(names1));//[1, 1, 1, 1] //指定替换元素 Arrays.fill(int[]a,fromIndex,toIndex,int val) int[]numbers={1,2,3}; System.out.println("fill前的数组内容:"+Arrays.toString(numbers));//[1, 2, 3] Arrays.fill(numbers,1,2,4); System.out.println("fill后的数组内容:"+Arrays.toString(numbers));//[1, 4, 3] }}
import java.util.ArrayList;import java.util.Arrays;public class Main { public static void main(String[] args) { /*sort*/ ArrayList<String> names = new ArrayList<>(); names.add("John"); names.add("Jane"); names.add("Bob"); names.add("Mary"); var names1=names.toArray(); System.out.println("sort前的数组内容:"+Arrays.toString(names1));//[John, Jane, Bob, Mary] Arrays.sort(names1); System.out.println("sort后的数组内容:"+Arrays.toString(names1));//[Bob, Jane, John, Mary] //数字排序 int[]numbers={1,2,3,5,6,4}; System.out.println("sort前的数组内容:"+Arrays.toString(numbers));//[1, 2, 3, 5, 6, 4] Arrays.sort(numbers); System.out.println("sort后的数组内容:"+Arrays.toString(numbers));//[1, 2, 3, 4, 5, 6] //指定元素位置排序 sort(int[]a,fromIndex,toIndex) int[]numbers1={1,2,3,5,6,4,8}; System.out.println("sort前的数组内容:"+Arrays.toString(numbers1));//[1, 2, 3, 5, 6, 4, 8] Arrays.sort(numbers1,0,6); System.out.println("sort后的数组内容:"+Arrays.toString(numbers1));//[1, 2, 3, 4, 5, 6, 8] }}
3.9 包装类
3.9.1 String类
在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串
3.9.1.1 创建字符串
import java.nio.Buffer;import java.util.ArrayList;import java.util.Arrays;public class Main { public static void main(String[] args) { //简单创建 String myName="王小明"; System.out.println(myName); /*构造函数创建*/ //字符串构造方法 String(String original) String hell=new String("Hello Java"); System.out.println(hell);//输出 Hello Java //char 数组构造 String(char[]) char[] helloArray = { 'h', 'e', 'l', 'l', 'o'}; String helloString = new String(helloArray); System.out.println(helloString);//输出 hello //char 数组构造 String(char[],offset,count) offset表示索引位置,count表示字符数量 String helloString1 = new String(helloArray,2,2); System.out.println(helloString1);//输出 ll //int 数组构造 String(int[],offset,count) String text = "Hello, 世界!"; int[] codePoints = text.codePoints().toArray();//必须是Unicode code points,否则乱码 String numStr=new String(codePoints,0,codePoints.length); System.out.println(numStr); //byte 数组构造 String(byte[]) String byteStr="Hello Java Byte String"; byte[] byteArray = byteStr.getBytes(); String byteArrayStr = new String(byteArray); System.out.println(byteArrayStr); //byte 数组构造 String(byte[],offset,length) String byteArrayStr1 = new String(byteArray,2,4); System.out.println(byteArrayStr1); //StringBuilder String builderStr=new String(new StringBuilder("Hello Java Builder")); System.out.println(builderStr); //StringBuffer String bufferStr=new String(new StringBuffer("Hello Java Buffer")); System.out.println(bufferStr); }}
3.9.1.2 字符串长度
public class Main { public static void main(String[] args) { //简单创建 String myName="王小明"; System.out.println(myName.length()); }}
3.9.1.3 连接字符串
public class Main { public static void main(String[] args) { //+号连接字符串 String myName="王小明"; String myTel="189XXXXXXXX"; String contactStr=myName+myTel; System.out.println(contactStr); //concat 连接字符串 String contactStr1=myName.concat(myTel); System.out.println(contactStr1); }}
3.9.1.4 格式化字符串
输出格式化数字可以使用 printf() 和 format() 方法。
String 类使用静态方法 format() 返回一个String 对象而不是 PrintStream 对象。
String 类的静态方法 format() 能用来创建可复用的格式化字符串,而不仅仅是用于一次打印输出。
格式化常用占位符:
%s - 字符串类型%d - 整数类型%f - 浮点类型%.nf - 浮点类型,保留到小数点后 n 位%tF - 日期 yyyy-MM-dd%tT - 时间格式 HH:mm:ss%x - 整数类型,十六进制表示(使用小写字母)%X - 整数类型,十六进制表示(使用大写字母)%% - 表示百分比,即显示成 % 字符import java.util.Date;public class Main { public static void main(String[] args) { // printf System.out.printf("浮点型变量的值为 " + "%f, 整型变量的值为 " + "%d, 字符串变量的值为 " + "is %s", 50.0, 20, "Hello Java"); //format String str=String.format("浮点型变量的值为 %.2f,整型变量的值为 %d,字符串变量的值为 %s",50.0, 20, "Hello Java"); System.out.println(str); // 日期 yyyy-MM-dd String dateStr=String.format("当前日期%tF",new Date()); System.out.println(dateStr); //时间 HH:mm:ss String timeStr=String.format("当前时间%tT",new Date()); System.out.println(timeStr); //百分比 String percentStr=String.format("占比 %d%%",50); System.out.println(percentStr); }}
3.9.1.5 String方法
方法 | 描述 | 返回值 |
char charAt(int index) | 返回指定索引处的 char 值。 | 返回指定索引处的字符 |
int compareTo(Object o) | 把这个字符串和另一个对象比较。 | 返回值是整型,它是先比较对应字符的大小(ASCII码顺序),如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的长度差值,如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,以此类推,直至比较的字符或被比较的字符有一方结束。 如果参数字符串等于此字符串,则返回值 0; 如果此字符串小于字符串参数,则返回一个小于 0 的值; 如果此字符串大于字符串参数,则返回一个大于 0 的值。 |
int compareTo(String anotherString) | 按字典顺序比较两个字符串。 | 同 int compareTo(Object o) |
int compareToIgnoreCase(String str) | 按字典顺序比较两个字符串,不考虑大小写。 | 如果参数字符串等于此字符串,则返回值 0; 如果此字符串小于字符串参数,则返回一个小于 0 的值; 如果此字符串大于字符串参数,则返回一个大于 0 的值。 |
String concat(String str) | 将指定字符串连接到此字符串的结尾。 | 返回连接后的新字符串 |
boolean contentEquals(StringBuffer sb) | 当且仅当字符串与指定的StringBuffer有相同顺序的字符时候返回真。 | 如字符串与指定 StringBuffer 表示相同的字符序列,则返回 true;否则返回 false。 |
static String copyValueOf(char[] data) | 返回指定数组中表示该字符序列的 String。 | |
static String copyValueOf(char[] data, int offset, int count) | 返回指定数组中表示该字符序列的 String。 | |
boolean endsWith(String suffix) | 测试此字符串是否以指定的后缀结束。 | 如果参数表示的字符序列是此对象表示的字符序列的后缀,则返回 true;否则返回 false |
boolean equals(Object anObject) | 将此字符串与指定的对象比较。 | |
boolean equalsIgnoreCase(String anotherString) | 将此 String 与另一个 String 比较,不考虑大小写。 | |
byte[] getBytes() | 使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 | |
byte[] getBytes(String charsetName) | 使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 | |
void getChars(int srcBegin,int srcEnd, char[] dst, int dstBegin) | 将字符从此字符串复制到目标字符数组。 | |
int hashCode() | 返回此字符串的哈希码。 | |
int indexOf(int ch) | 返回指定字符在此字符串中第一次出现处的索引。 | |
int indexOf(int ch, int fromIndex) | 返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索。 | |
int indexOf(String str) | 返回指定子字符串在此字符串中第一次出现处的索引。 | |
int indexOf(String str, int fromIndex) | 返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。 | |
String intern() | 返回字符串对象的规范化表示形式。 | |
int lastIndexOf(int ch) | 返回指定字符在此字符串中最后一次出现处的索引。 | |
int lastIndexOf(int ch, int fromIndex) | 返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索。 | |
int lastIndexOf(String str) | 返回指定子字符串在此字符串中最右边出现处的索引。 | |
int lastIndexOf(String str, int fromIndex) | 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。 | |
int length() | 返回此字符串的长度。 | |
boolean matches(String regex) | 告知此字符串是否匹配给定的正则表达式。 | |
boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) |
| |
boolean regionMatches(int toffset, String other, int ooffset, int len) | 测试两个字符串区域是否相等。 | |
String replace(char oldChar, char newChar) | 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。 | |
String replaceAll(String regex, String replacement) | 使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。 | |
String replaceFirst(String regex, String replacement) | 使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。 | |
String[] split(String regex) | 根据给定正则表达式的匹配拆分此字符串。 | |
String[] split(String regex, int limit) | 根据匹配给定的正则表达式来拆分此字符串。 | |
boolean startsWith(String prefix) | 测试此字符串是否以指定的前缀开始。 | |
boolean startsWith(String prefix, int toffset) | 测试此字符串从指定索引开始的子字符串是否以指定前缀开始。 | |
CharSequence subSequence(int beginIndex, int endIndex) | 返回一个新的字符序列,它是此序列的一个子序列。 | |
String substring(int beginIndex) | 返回一个新的字符串,它是此字符串的一个子字符串。 | |
String substring(int beginIndex, int endIndex) | 返回一个新字符串,它是此字符串的一个子字符串。 | |
char[] toCharArray() | 将此字符串转换为一个新的字符数组。 | |
String toLowerCase() | 使用默认语言环境的规则将此 String 中的所有字符都转换为小写。 | |
String toLowerCase(Locale locale) | 使用给定 Locale 的规则将此 String 中的所有字符都转换为小写。 | |
String toString() | 返回此对象本身(它已经是一个字符串!)。 | |
String toUpperCase() | 使用默认语言环境的规则将此 String 中的所有字符都转换为大写。 | |
String toUpperCase(Locale locale) | 使用给定 Locale 的规则将此 String 中的所有字符都转换为大写。 | |
String trim() | 返回字符串的副本,忽略前导空白和尾部空白。 | |
static String valueOf(primitive data type x) | 返回给定data type类型x参数的字符串表示形式。 | |
contains(CharSequence chars) | 判断是否包含指定的字符系列。 | |
isEmpty() | 判断字符串是否为空。 |
部分方法示例代码
public class Main { public static void main(String[] args) { /*String 方法*/ String str="Hello Java"; //charAt(int index) 返回指定索引处的 char 值 System.out.println("返回索引为6的值:"+str.charAt(6));// J //compareTo 把这个字符串和另一个对象比较 System.out.println("Hello Java 与 Hello Java的比较:"+str.compareTo("Hello Java"));// 0 System.out.println("Hello Java 与 Hello World的比较:"+str.compareTo("Hello World"));// -13 System.out.println("Hello Java 与 Hello Abc的比较:"+str.compareTo("Hello Abc"));// 9 //compareToIgnoreCase() 按字典顺序比较两个字符串,不考虑大小写 System.out.println("STRING 与 string的字典顺序比较:"+"STRING".compareToIgnoreCase("string"));// 0 System.out.println("STRING 与 string123的字典顺序比较:"+"STRING".compareToIgnoreCase("string123"));// -3 System.out.println("string123 与 STRING的字典顺序比较:"+"string123".compareToIgnoreCase("STRING"));// 3 //concat 连接字符串 System.out.println("Hello 连接 World:"+"Hello".concat("World"));// HelloWorld //contentEquals() 将此字符串与指定的 StringBuffer 比较 System.out.println("String 和StringBuffer比较:"+"String".contentEquals(new StringBuffer("String")));// true System.out.println("String 和StringBuffer比较:"+"String".contentEquals(new StringBuffer("String1")));// false //copyValueOf() 返回指定数组中表示该字符序列的 String char[] charStr=new char[]{'a','b','c','d','e','f'}; System.out.println("String copyValueOf 全部数据:"+String.copyValueOf(charStr));//abcdef System.out.println("String copyValueOf 从索引2开始三个元素:"+String.copyValueOf(charStr,2,3));//cde //endWith 字符串是否以指定的后缀结束 System.out.println("String 字符串以g结束:"+"String".endsWith("g"));// true System.out.println("String 字符串以A结束:"+"String".endsWith("A"));// false //startWith System.out.println("String 字符串以g开始:"+"String".startsWith("g"));// false System.out.println("String 字符串以s开始:"+"String".startsWith("s"));// false System.out.println("String 字符串以S开始:"+"String".startsWith("S"));// true }}
3.9.2 StringBuffer 和 StringBuilder 类
当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。
和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用 StringBuffer。
StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。
3.9.2.1 StringBuilder
构造方法:
StringBuilder():构造一个字符串构建器,其中不包含任何字符,初始容量为16个字符。StringBuilder(int capacity):构造一个字符串构建器,其中没有字符,并且具有 capacity参数指定的初始容量。StringBuilder(CharSequence seq):构造一个字符串构建器,其中包含与指定的 CharSequence相同的字符。StringBuilder(String str):构造一个初始化为指定字符串内容的字符串构建器。部分方法实例代码:
public class Main { public static void main(String[] args) { /*StringBuilder*/ StringBuilder strBuilder=new StringBuilder(); //将指定的字符串追加到此字符 strBuilder.append("Hello Java"); System.out.println(strBuilder.toString());//Hello Java strBuilder.append(" Code"); System.out.println(strBuilder.toString());//Hello Java Code //指定位置插入 strBuilder.insert(2,"Study"); System.out.println(strBuilder.toString());//HeStudyllo Java Code //指定位置删除-deleteCharAt strBuilder.deleteCharAt(2); System.out.println(strBuilder.toString());//Hetudyllo Java Code //指定位置删除-delete,不包含结束索引 strBuilder.delete(2,6); System.out.println(strBuilder.toString());//Hello Java Code //指定位置替换 包含结束索引 strBuilder.replace(11,15,""); System.out.println(strBuilder.toString());//Hello Java }}
StringBuilder更多方法请参见官网或者其他相关学习网站的相关说明
3.9.2.2 StringBuffer
构造方法:
StringBuffer():构造一个字符串缓冲区,其中没有字符,初始容量为16个字符。StringBuffer(int capacity):构造一个字符串缓冲区,其中没有字符和指定的初始容量。StringBuffer(CharSequence seq):构造一个字符串缓冲区,其中包含与指定的 CharSequence相同的字符。StringBuffer(String str):构造一个初始化为指定字符串内容的字符串缓冲区。部分方法实例代码:
public class Main { public static void main(String[] args) { /*StringBuffer*/ StringBuffer strBuffer=new StringBuffer(); //将指定的字符串追加到此字符 strBuffer.append("Hello Java"); System.out.println(strBuffer.toString());//Hello Java strBuffer.append(" Code"); System.out.println(strBuffer.toString());//Hello Java Code //指定位置插入 strBuffer.insert(2,"Study"); System.out.println(strBuffer.toString());//HeStudyllo Java Code //指定位置删除-deleteCharAt strBuffer.deleteCharAt(2); System.out.println(strBuffer.toString());//Hetudyllo Java Code //指定位置删除-delete,不包含结束索引 strBuffer.delete(2,6); System.out.println(strBuffer.toString());//Hello Java Code //指定位置替换 包含结束索引 strBuffer.replace(11,15,""); System.out.println(strBuffer.toString());//Hello Java }}
StringBuffer更多方法请参见官网或者其他相关学习网站的相关说明
3.9.3 Character 类
Character 类用于对单个字符进行操作。Character 类在对象中包装一个基本类型 char 的值
转义序列
转义序列 | 描述 |
\t | 在文中该处插入一个tab键 |
\b | 在文中该处插入一个后退键 |
\n | 在文中该处换行 |
\r | 在文中该处插入回车 |
\f | 在文中该处插入换页符 |
\' | 在文中该处插入单引号 |
\" | 在文中该处插入双引号 |
\\ | 在文中该处插入反斜杠 |
Character方法
方法 | 描述 |
isLetter() | 是否是一个字母 |
isDigit() | 是否是一个数字字符 |
isWhitespace() | 是否是一个空白字符 |
isUpperCase() | 是否是大写字母 |
isLowerCase() | 是否是小写字母 |
toUpperCase() | 指定字母的大写形式 |
toLowerCase() | 指定字母的小写形式 |
toString() | 返回字符的字符串形式,字符串的长度仅为1 |
public class Main { public static void main(String[] args) { /*Character*/ //原始字符 'a' 装箱到 Character 对象 ch 中 Character ch ='a'; System.out.println(ch); System.out.println((int)ch); /*Character 方法*/ //isLetter 用于判断指定字符是否为字母 System.out.println("c是否为字母:"+Character.isLetter('c'));// true System.out.println("5是否为字母:"+Character.isLetter('5'));// false //isDigit 用于判断指定字符是否为数字 System.out.println("c是否为数字:"+Character.isDigit('c'));// false System.out.println("5是否为数字:"+Character.isDigit('5'));// true //isWhitespace 用于判断指定字符是否为空白字符,空白符包含:空格、tab 键、换行符 System.out.println("c是否为空白字符:"+Character.isWhitespace('c'));// false System.out.println("空格是否为空白字符:"+Character.isWhitespace(' '));// true System.out.println("tab键是否为空白字符:"+Character.isWhitespace('\t'));// true System.out.println("换行是否为空白字符:"+Character.isWhitespace('\n'));// true //isUpperCase 用于判断指定字符是否为大写字母 System.out.println("c是否为大写字母:"+Character.isUpperCase('c'));// false System.out.println("C是否为大写字母:"+Character.isUpperCase('C'));// true //isLowerCase 用于判断指定字符是否为小写字母 System.out.println("c是否为小写字母:"+Character.isLowerCase('c'));// true System.out.println("C是否为小写字母:"+Character.isLowerCase('C'));// false //toUpperCase 用于将小写字符转换为大写;返回转换后字符的大写形式,如果有的话;否则返回字符本身 System.out.println("c转为大写字母:"+Character.toUpperCase('c'));// C System.out.println("5转为大写字母:"+Character.toUpperCase('5'));// 5 //toLowerCase 用于将大写字符转换为小写;返回转换后字符的小写形式,如果有的话;否则返回字符本身 System.out.println("C转为小写字母:"+Character.toLowerCase('C'));// c System.out.println("5转为小写字母:"+Character.toLowerCase('5'));// 5 //toString() 方法用于返回一个表示指定 char 值的 String 对象。结果是长度为 1 的字符串,仅由指定的 char 组成 System.out.println("C转为字符串:"+Character.toString('C'));// C }}
3.9.4 Number & Math 类
3.9.4.1 Number类
包装类型都是用 final 声明了,不可以被继承重写;在实际情况中编译器会自动的将基本数据类型装箱成对象类型,或者将对象类型拆箱成基本数据类型
基本数据类型对应的包装类
包装类 | 基本数据类型 |
Boolean | boolean |
Byte | byte |
Short | short |
Integer | int |
Long | long |
Character | char |
Float | float |
Double | double
|
3.9.4.2 Math类
Math 包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数。
Math 的方法都被定义为 static 形式,通过 Math 类可以在主函数中直接调用。
public class Main { public static void main(String[] args) { /*Math类*/ System.out.println("90 度的正弦值:" + Math.sin(Math.PI/2)); System.out.println("0度的余弦值:" + Math.cos(0)); System.out.println("60度的正切值:" + Math.tan(Math.PI/3)); System.out.println("1的反正切值: " + Math.atan(1)); System.out.println("π/2的角度值:" + Math.toDegrees(Math.PI/2)); System.out.println("圆周率:"+Math.PI); }}
3.9.4.3 Number &Math类方法
所属类 | 方法 | 描述 |
Number | xxxValue() | 将 Number 对象转换为xxx数据类型的值并返回。具体参加下方xxxValue方法 |
Number | compareTo() | 将number对象与参数比较。 如果指定的数与参数相等返回 0。 |
Number | equals() | 判断number对象是否与参数相等。 如 Number 对象不为 Null,且与方法的参数类型与数值都相等返回 True,否则返回 False |
Number | valueOf() | 返回一个 Number 对象指定的内置数据类型。 valueOf(int i):返回一个表示指定的 int 值的 Integer 实例。 |
Number | toString() | 以字符串形式返回值。 toString(): 返回表示 Integer 值的 String 对象。 |
Number | parseInt() | 将字符串解析为int类型。 parseInt(String s):返回用十进制参数表示的整数值,s -- 十进制表示的字符串 |
Math | abs() | 返回参数的绝对值。 |
Math | ceil() | 返回大于等于( >= )给定参数的的最小整数,类型为双精度浮点型。 |
Math | floor() | 返回小于等于(<=)给定参数的最大整数 。 |
Math | rint() | 返回与参数最接近的整数。返回类型为double。 |
Math | round() | 它表示四舍五入,算法为 Math.floor(x+0.5),即将原来的数字加上 0.5 后再向下取整,所以,Math.round(11.5) 的结果为12,Math.round(-11.5) 的结果为-11。 |
Math | min() | 返回两个参数中的最小值。 |
Math | max() | 返回两个参数中的最大值。 |
Math | exp() | 返回自然数底数e的参数次方。 |
Math | log() | 返回参数的自然数底数的对数值。 |
Math | pow() | 返回第一个参数的第二个参数次方。 |
Math | sqrt() | 求参数的算术平方根。 |
Math | sin() | 求指定double类型参数的正弦值。 |
Math | cos() | 求指定double类型参数的余弦值。 |
Math | tan() | 求指定double类型参数的正切值。 |
Math | asin() | 求指定double类型参数的反正弦值。 |
Math | acos() | 求指定double类型参数的反余弦值。 |
Math | atan() | 求指定double类型参数的反正切值。 |
Math | atan2() | 将笛卡尔坐标转换为极坐标,并返回极坐标的角度值。 |
Math | toDegrees() | 将参数转化为角度。 |
Math | toRadians() | 将角度转换为弧度。 |
Math | random() | 返回一个随机数。 |
xxxValue方法
类型 | 方法及描述 |
byte | byteValue() :以 byte 形式返回指定的数值。 |
abstract double | doubleValue() :以 double 形式返回指定的数值。 |
abstract float | floatValue() :以 float 形式返回指定的数值。 |
abstract int | intValue() :以 int 形式返回指定的数值。 |
abstract long | longValue() :以 long 形式返回指定的数值。 |
short | shortValue() :以 short 形式返回指定的数值。 |
public class Main { public static void main(String[] args) { /*Math类方法*/ //xxxValue() 将 Number 对象转换为xxx数据类型的值并返回 Integer x = 5; System.out.println("返回 byte 原生数据类型:"+ x.byteValue()); System.out.println("返回 double 原生数据类型:"+x.doubleValue()); System.out.println( "返回 long 原生数据类型:"+x.longValue()); //compareTo() 将 Number 对象与方法的参数进行比较 // 如果指定的数与参数相等返回 0。 //如果指定的数小于参数返回 -1。 //如果指定的数大于参数返回 1。 System.out.println(x.compareTo(3)); System.out.println(x.compareTo(5)); System.out.println(x.compareTo(8)); //valueOf 返回给定参数的原生 Number 对象值,参数可以是原生数据类型, String等 Integer d =Integer.valueOf(9); Double c = Double.valueOf(5); Float a = Float.valueOf("80"); Integer b = Integer.valueOf("444",16); // 使用 16 进制 System.out.println(d);//9 System.out.println(c);//5.0 System.out.println(a);//80.0 System.out.println(b);// 1092 // toString System.out.println("toString方法:"+x.toString()); System.out.println("带参 toString方法:"+Integer.toString(12)); //parseInt 将字符串解析为int类型 System.out.println("parseInt:"+Integer.parseInt("15")); System.out.println("parseInt 16进制:"+Integer.parseInt("15",16)); // abs 返回绝对值 System.out.println("double 绝对值:"+Math.abs(-80.0)); System.out.println("float 绝对值:"+Math.abs(-70.0f)); System.out.println("int 绝对值:"+Math.abs(-9)); System.out.println("long 绝对值:"+Math.abs(-1234567890333337777l)); /*Math 的 floor,round 和 ceil 方法实例比较 ceil() 对一个数进行上舍入,返回值大于或等于给定的参数,类型为双精度浮点型 floor() 对一个数进行下舍入,返回给定参数最大的整数,该整数小于或等给定的参数 round() 方法返回一个最接近的 int、long 型值,四舍五入 * */ double dx=1.4; System.out.println("Math.ceil:"+Math.ceil(dx));//2.0 System.out.println("Math.floor:"+Math.floor(dx));//1.0 System.out.println("Math.round:"+Math.round(dx));//1 double dx1=-1.4; System.out.println("Math.ceil:"+Math.ceil(dx1));//-1.0 System.out.println("Math.floor:"+Math.floor(dx1));//-2.0 System.out.println("Math.round:"+Math.round(dx1));//-1 }}
3.9.5 日期和时间
3.9.5.1 Date的创建和方法
java.util 包提供了 Date 类来封装当前的日期和时间。 Date 类提供两个构造函数来实例化 Date 对象
第一个构造函数使用当前日期和时间来初始化对象:Date()
第二个构造函数接收一个参数,该参数是从 1970 年 1 月 1 日起的毫秒数:Date(long millisec)
方法 | 描述 |
boolean after(Date date) | 若当调用此方法的Date对象在指定日期之后返回true,否则返回false。 |
boolean before(Date date) | 若当调用此方法的Date对象在指定日期之前返回true,否则返回false。 |
Object clone() | 返回此对象的副本。 |
int compareTo(Date date) | 比较当调用此方法的Date对象和指定日期。两者相等时候返回0。调用对象在指定日期之前则返回负数。调用对象在指定日期之后则返回正数。 |
int compareTo(Object obj) | 若obj是Date类型则操作等同于compareTo(Date) 。否则它抛出ClassCastException。 |
boolean equals(Object date) | 当调用此方法的Date对象和指定日期相等时候返回true,否则返回false。 |
long getTime() | 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。 |
int hashCode() | 返回此对象的哈希码值。 |
void setTime(long time) | 用自1970年1月1日00:00:00 GMT以后time毫秒数设置时间和日期。 |
String toString() | 把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。 |
import java.util.Date;import java.util.Calendar;public class Main { public static void main(String[] args) { /*日期Date*/ var currDate = new Date();//当前日期 System.out.println("当前日期:"+currDate); var msDate = new Date(currDate.getTime()); System.out.println("当前日期(带有毫秒参数):"+msDate); //after 若当调用此方法的Date对象在指定日期之后返回true,否则返回false Calendar calendar = Calendar.getInstance(); // 获取当前日期 calendar.add(Calendar.DATE, -1); // 将日期减去一天 Date yesterday = calendar.getTime(); // 获取前一天的Date对象 System.out.println("今天在昨天之后:"+currDate.after(yesterday));// true System.out.println("昨天在今天之后:"+yesterday.after(currDate));// false //before 若当调用此方法的Date对象在指定日期之前返回true,否则返回false System.out.println("今天在昨天之前:"+currDate.before(yesterday));// false System.out.println("昨天在今天之前:"+yesterday.before(currDate));// true //clone 拷贝副本 System.out.println("今天日期的副本是:"+currDate.clone()); //compareTo(Date date) 比较当调用此方法的Date对象和指定日期。两者相等时候返回0。调用对象在指定日期之前则返回负数。调用对象在指定日期之后则返回正数。 System.out.println("currDate和msDate一样:"+currDate.compareTo(msDate)); //0 System.out.println("昨天和今天一样:"+yesterday.compareTo(currDate));// -1 //equals 当调用此方法的Date对象和指定日期相等时候返回true,否则返回false System.out.println("currDate equals msDate:"+currDate.equals(msDate)); // true System.out.println("昨天 equals 今天:"+yesterday.equals(currDate));// false //getTime() 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数 System.out.println("当前日期的毫秒数:"+currDate.getTime()); //hashCode() 返回此对象的哈希码值 System.out.println("当前日期的哈希码值:"+currDate.hashCode()); //setTime(long time) 用自1970年1月1日00:00:00 GMT以后time毫秒数设置时间和日期 Date yesterday1 = (Date)yesterday.clone(); yesterday1.setTime(5000); System.out.println("time毫秒数设置时间和日期:"+yesterday1); //toString() 日期转换为字符串 // 把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。 System.out.println("当前日期字符串:"+currDate); //sleep()使当前线程进入停滞状态(阻塞当前线程),让出CPU的使用、目的是不让当前线程独自霸占该进程所获的CPU资源,以留一定时间给其他线程执行的机会。 //注:必须添加 try catch 容错语句 try{ System.out.println("休眠前的时间:"+new Date()); Thread.sleep(3000); // 休眠3秒 System.out.println("休眠3s后的时间:"+new Date()); } catch ( Exception e ) { System.out.println("Got an exception!"); } //计算时间差 注:必须添加 try catch 容错语句 try { long start = System.currentTimeMillis( ); System.out.println(new Date()); Thread.sleep(3000); System.out.println(new Date()); long end = System.currentTimeMillis( ); long diff = end - start; System.out.println("Difference is : " + diff); } catch (Exception e) { System.out.println("Got an exception!"); } }}
3.9.5.2 日期格式化
使用 SimpleDateFormat 格式化日期
SimpleDateFormat 是一个以语言环境敏感的方式来格式化和分析日期的类。SimpleDateFormat 允许你选择任何用户自定义日期时间格式来运行。
日期和时间的格式化编码:
字母 | 描述 | 示例 |
G | 纪元标记 | AD |
y | 四位年份 | 2001 |
M | 月份 | July or 07 |
d | 一个月的日期 | 10 |
h | A.M./P.M. (1~12)格式小时 | 12 |
H | 一天中的小时 (0~23) | 22 |
m | 分钟数 | 30 |
s | 秒数 | 55 |
S | 毫秒数 | 234 |
E | 星期几 | Tuesday |
D | 一年中的日子 | 360 |
F | 一个月中第几周的周几 | 2 (second Wed. in July) |
w | 一年中第几周 | 40 |
W | 一个月中第几周 | 1 |
a | A.M./P.M. 标记 | PM |
k | 一天中的小时(1~24) | 24 |
K | A.M./P.M. (0~11)格式小时 | 10 |
z | 时区 | Eastern Standard Time |
' | 文字定界符 | Delimiter |
" | 单引号 | ` |
import java.text.SimpleDateFormat;import java.util.Date;import java.util.Calendar;public class Main { public static void main(String[] args) { /*使用 SimpleDateFormat 格式化日期*/ var currDate = new Date();//当前日期 System.out.println("当前日期:"+currDate); //12小时制格式化 SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss"); System.out.println("当前时间为(12小时制): " + ft.format(currDate)); //24小时制格式化 SimpleDateFormat ft24 = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss"); System.out.println("当前时间为(24小时制): " + ft24.format(currDate)); //带有毫秒的格式化 SimpleDateFormat ftMs24 = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss:SS"); System.out.println("当前时间为(24小时制 毫秒): " + ftMs24.format(currDate)); //带有 星期的日期格式化 SimpleDateFormat ftXq24 = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss EE"); System.out.println("当前时间为(24小时制 星期): " + ftXq24.format(currDate)); //纯星期的日期格式化 SimpleDateFormat ftXq = new SimpleDateFormat ("EE"); System.out.println("今天是星期几中的: " + ftXq.format(currDate)); //字符串转日期 注:必须添加 try catch 容错语句 try{ SimpleDateFormat ftStr = new SimpleDateFormat("yyyy-MM-dd"); String strDate="2024-02-03"; Date dt=ftStr.parse(strDate); System.out.println("字符串转日期:"+dt); } catch ( Exception e ){ System.out.println("Unparseable using " + ft); } }}
使用printf格式化日期
printf 方法可以很轻松地格式化时间和日期。使用两个字母格式,它以 %t 开头并且以下面表格中的一个字母结尾。
日期格式化转换符
转换符 | 说明 | 示例 |
%ta | 本地化的星期缩写 | 周二 |
%tA | 本地化的星期全名 | 星期二 |
%tb | 本地化的月份缩写 | 7月 |
%tB | 本地化的月份全名 | 七月 |
%tc | 包括全部日期和时间信息 | 周二 7月 16 16:32:24 CST 2024 |
%td | 两位数的日期 | 比如当前日期是2024-07-16,那么输出的是16 |
%tD | "月/日/年"格式 | 07/16/24 |
%te | 一位或两位数的日期 | 比如当前日期是2024-07-16,那么输出的是16;如果是2024-07-08,那么输出的是8 |
%tF | "年-月-日"格式 | 2024-07-16 |
%tH | 24小时制的小时数 |
|
%tl | 12小时制的小时数 |
|
%tm | 输出两位数的月份 |
|
%tM | 输出分钟数 |
|
%tp | 输出上午或下午 |
|
%tr | 输出本地化的"HH:MM:SS PM"格式(12时制) | 02:25:51 下午 |
%tR | "HH:MM"格式(24时制) | 14:28 |
%tS | 输出秒数 |
|
%tT | "HH:MM:SS"格式(24时制) | 14:28:16 |
%ty | 输出两位年份数 | 24 |
%tY | 输出四位年份数 | 2024 |
%tZ | 输出时区 |
|
import java.util.Date;public class Main { public static void main(String[] args) { /*使用 printf 格式化日期*/ var currDate = new Date();//当前日期 System.out.println("当前日期:"+currDate); //%ta 输出星期的缩写 System.out.printf("星期的缩写: %ta "+"\n", currDate); //%tA 输出星期的全名 System.out.printf("星期的全名:%tA"+"\n",currDate); //%tb 输出月份的缩写 System.out.printf("月份的缩写: %tb "+"\n", currDate); //%tB 输出月份的全名 System.out.printf("月份的全名:%tB"+"\n",currDate); //%tc 包括全部日期和时间信息 System.out.printf("日期和时间信息:%tc"+"\n",currDate); //%td 输出当前两位数日期(Day) System.out.printf("当前两位数日期(Day):%td"+"\n",currDate); //%tD 输出"月/日/年"格式 System.out.printf("月/日/年信息:%tD"+"\n",currDate); //%te 一位或两位数的日期(Day) System.out.printf("一位或两位数的日期(Day):%te"+"\n",currDate); //%tF 输出"年-月-日"格式 System.out.printf("年-月-日:%tF"+"\n",currDate); //%tH 输出24小时制的小时数 System.out.printf("24小时制的小时数:%tH"+"\n",currDate); //%tl 输出12小时制的小时数 System.out.printf("12小时制的小时数:%tl"+"\n",currDate); //%tm 输出两位数的月份 System.out.printf("两位数的月份:%tm"+"\n",currDate); //%tM 输出分钟数 System.out.printf("分钟数:%tM"+"\n",currDate); //%tp 输出上午或下午 System.out.printf("上午或下午:%tp"+"\n",currDate); //%tr 输出本地化的"HH:MM:SS PM"格式(12小时制) System.out.printf("HH:MM:SS PM:%tr"+"\n",currDate); //%tR 输出HH:MM 24小时制 System.out.printf("HH:MM:%tR"+"\n",currDate); //%tS 输出秒数 System.out.printf("秒数:%tS"+"\n",currDate); //%tT 输出输出本地化的"HH:MM:SS PM"格式(24小时制) System.out.printf("HH:MM:SS:%tT"+"\n",currDate); //%ty 输出两位年份 System.out.printf("两位年份:%ty"+"\n",currDate); //%tY 输出四位年份 System.out.printf("四位年份:%tY"+"\n",currDate); //%tZ 输出时区 System.out.printf("时区:%tZ"+"\n",currDate); }}
如果想使用字符串日期格式化,转换字符同printf
import java.util.Date;public class Main { public static void main(String[] args) { /*使用 printf 格式化日期*/ var currDate = new Date();//当前日期 System.out.println("当前日期:"+currDate); String strDate=String.format("当前日期:%tF",currDate); System.out.println(strDate); String strXq=String.format("今天是:%tA",currDate); System.out.println(strXq); }}
3.9.5.3 Calendar类
当我们想获取或者设置日期的特定部分内容,需要使用Calendar类,比如获取日期的年份,设置年份加1等。
Calendar类对象的字段类型
常量 | 描述 |
---|---|
Calendar.YEAR | 年份 |
Calendar.MONTH | 月份 |
Calendar.DATE | 日期 |
Calendar.DAY_OF_MONTH | 日期,和上面的字段意义完全相同 |
Calendar.HOUR | 12小时制的小时 |
Calendar.HOUR_OF_DAY | 24小时制的小时 |
Calendar.MINUTE | 分钟 |
Calendar.SECOND | 秒 |
Calendar.DAY_OF_WEEK | 星期几 |
//创建一个代表系统当前日期的Calendar对象,默认是当前日期
Calendar c = Calendar.getInstance();
//创建一个代表2009年6月12日的Calendar对象
Calendar c1 = Calendar.getInstance();
c1.set(2009, 6 - 1, 12);
对象类型的设置通过set或者add实现
一些set方法
set(int field,int value):将给定的日历 对象字段值 设置为给定的 valueset(int year, int month, int date):设置日历字段 年、月、日 的值set(int year,int month,int date,hourOfDay,int minute):置日历字段 年、月、日、小时、分钟 的值set(int year,int month,int date,hourOfDay,int minute,int second):设置日历字段 Y年、月、日、小时、分钟、秒 的值setFirstDayOfWeek(int value): 设置一周的第一天setLenient(boolean lenient):指定日期/时间解释是否宽松setMinimalDaysInFirstWeek(int value):设置一年中第一周所需的最少天数setTime(Date date):用给定的 Date. 设置日历的时间setTimeInMillis(long millis):根据给定的 毫秒 值设置 Calendar 的当前时间setTimeZone(TimeZone value):使用给定的时区 value 设置时区add方法
add(int filed,int amount):根据日历的规则在给定的日历字段中添加或减去指定的时间量
日期指定内容的获取通过get实现
一些get方法
get(int field):返回给定日历字段的值Date getTime():此日历时间值的 Date 对象TimeZone getTimeZone():获取时区import java.text.SimpleDateFormat;import java.util.Date;import java.util.Calendar;import java.util.TimeZone;public class Main { public static void main(String[] args) { /*Calendar类*/ Calendar c1 = Calendar.getInstance(); System.out.println("Calendar对象日期:"+c1.getTime()); //set(int field,int value) c1.set(Calendar.YEAR,2020); System.out.println("Calendar set(int field,int value) 对象日期:"+c1.getTime()); // set(int year,int month,int date) c1.set(2022,5,25); System.out.println("Calendar set(int year,int month,int date) 对象日期:"+c1.getTime()); //set(int year,int month,int date,hourOfDay,int minute) c1.set(2022,6,30,16,30); System.out.println("Calendar set(int year,int month,int date,hourOfDay,int minute) 对象日期:"+c1.getTime()); //set(int year,int month,int date,hourOfDay,int minute,int second) c1.set(2022,7,31,16,30,30); System.out.println("Calendar set(int year,int month,int date,hourOfDay,int minute,int second) 对象日期:"+c1.getTime()); //setTime(Date date); try{ String strDate="2020-01-05 14:30:30"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date dt=sdf.parse(strDate); c1.setTime(dt); System.out.println("Calendar setTime(Date date) 对象日期:"+c1.getTime()); } catch ( Exception e ){ System.out.println(e.getMessage()); } // 设置一周的第一天:setFirstDayOfWeek(int value); Calendar c2 = Calendar.getInstance(); c2.setFirstDayOfWeek(Calendar.FRIDAY); System.out.println("Calendar setFirstDayOfWeek(int value) 对象日期:"+c2.getTime()); System.out.println("一周的第一天: " +c2.getFirstDayOfWeek()); //指定日期/时间解释是否宽松 setLenient(boolean lenient); System.out.println("当前日期/时间解释是否宽松: " +c1.isLenient()); c1.setLenient(!c1.isLenient()); System.out.println("修改指定日期/时间解释是否宽松::"+c1.isLenient()); //setMinimalDaysInFirstWeek(int value) //setTimeInMillis(long millis) //etTimeZone(TimeZone value) //setWeekDate(int weekYear,int weekOfYear,int dayOfWeek) //isSet(int field) //根据日历的规则在给定的日历字段中添加或减去指定的时间量 add(int filed,int amount) Calendar c3 = Calendar.getInstance(); System.out.println("当前日期: " +c3.getTime()); c3.add(Calendar.YEAR,-1); System.out.println("年份减1后的日期: " +c3.getTime()); c3.add(Calendar.YEAR,1); System.out.println("年份加1后的日期: " +c3.getTime()); c3.add(Calendar.MONTH,2); System.out.println("月份加2后的日期: " +c3.getTime()); c3.add(Calendar.DATE,2); System.out.println("日期加2后的日期: " +c3.getTime()); }}
import java.text.SimpleDateFormat;import java.util.Date;import java.util.Calendar;import java.util.Locale;import java.util.TimeZone;public class Main { public static void main(String[] args) { /*Calendar类*/ Calendar c1 = Calendar.getInstance(); //get(int field):返回给定日历字段的值 System.out.println("Calendar get(int field) 获取当前年份:"+c1.get(Calendar.YEAR)); System.out.println("Calendar get(int field) 获取当前月份:"+(c1.get(Calendar.MONTH)+1)); // Date getTime():此日历时间值的 Date 对象 System.out.println("Calendar对象日期:"+c1.getTime()); //TimeZone getTimeZone():获取时区 System.out.println("Calendar getTimeZone() 获取时区:"+c1.getTimeZone()); }}
3.9.5.4 GregorianCalendar类
GregorianCalendar 类是Calendar 的一个具体子类,提供了世界上大部分地区使用的标准日历系统。以下是关于GregorianCalendar 的要点:
它是一种混合日历,同时支持儒略历和公历系统,并支持单个不连续性,默认情况下对应于公历制定时的公历日期。儒略历每四年指定闰年,而公历省略不能被 400 整除的世纪年。GregorianCalendar定义了两个字段:AD和BC,这是代表公历定义的两个时代
AD :这是指示共同时代 (Anno Domini) 的 ERA 字段的值,也称为 CEBC : 这是 ERA 字段的值,表示普通时代(基督之前)之前的时期,也称为 BCE构造函数和说明
构造函数 | 说明 |
GregorianCalendar() | 在具有默认语言环境的默认时区内使用当前时间构造一个默认的 GregorianCalendar。 |
GregorianCalendar(int year, int month, int date) | 在具有默认语言环境的默认时区内构造一个带有给定日期设置的 GregorianCalendar |
GregorianCalendar(int year, int month, int date, int hour, int minute) | 为具有默认语言环境的默认时区构造一个具有给定日期和时间设置的 GregorianCalendar。 |
GregorianCalendar(int year, int month, int date, int hour, int minute, int second) | 为具有默认语言环境的默认时区构造一个具有给定日期和时间设置的 GregorianCalendar。 |
GregorianCalendar(Locale aLocale) | 在具有给定语言环境的默认时区内构造一个基于当前时间的 GregorianCalendar。 |
GregorianCalendar(TimeZone zone) | 在具有默认语言环境的给定时区内构造一个基于当前时间的 GregorianCalendar。 |
GregorianCalendar(TimeZone zone, Locale aLocale) | 在具有给定语言环境的给定时区内构造一个基于当前时间的 GregorianCalendar。 |
GregorianCalendar 类提供的一些有用的方法列表
方法 | 说明 |
void add(int field, int amount) | 根据日历规则,将指定的(有符号的)时间量添加到给定的日历字段中。 |
protected void computeFields() | 转换UTC毫秒值为时间域值 |
protected void computeTime() | 覆盖Calendar ,转换时间域值为UTC毫秒值 |
boolean equals(Object obj) | 比较此 GregorianCalendar 与指定的 Object。 |
int get(int field) | 获取指定字段的时间值 |
int getActualMaximum(int field) | 返回当前日期,给定字段的最大值 |
int getActualMinimum(int field) | 返回当前日期,给定字段的最小值 |
int getGreatestMinimum(int field) | 返回此 GregorianCalendar 实例给定日历字段的最高的最小值。 |
Date getGregorianChange() | 获取公历更改日期。 |
int getLeastMaximum(int field) | 返回此 GregorianCalendar 实例给定日历字段的最低的最大值 |
int getMaximum(int field) | 返回此 GregorianCalendar 实例的给定日历字段的最大值。 |
Date getTime() | 获取日历当前时间。 |
long getTimeInMillis() | 获取用长整型表示的日历的当前时间 |
TimeZone getTimeZone() | 获取时区。 |
int getMinimum(int field) | 返回给定字段的最小值。 |
int hashCode() | 重写hashCode. |
boolean isLeapYear(int year) | 确定给定的年份是否为闰年。 |
void roll(int field, boolean up) | 在给定的时间字段上添加或减去(上/下)单个时间单元,不更改更大的字段。 |
void set(int field, int value) | 用给定的值设置时间字段。 |
void set(int year, int month, int date) | 设置年、月、日的值。 |
void set(int year, int month, int date, int hour, int minute) | 设置年、月、日、小时、分钟的值。 |
void set(int year, int month, int date, int hour, int minute, int second) |
|
void setGregorianChange(Date date) | 设置 GregorianCalendar 的更改日期。 |
void setTime(Date date) | 用给定的日期设置Calendar的当前时间。 |
void setTimeInMillis(long millis) | 用给定的long型毫秒数设置Calendar的当前时间。 |
void setTimeZone(TimeZone value) | 用给定时区值设置当前时区。 |
String toString() | 返回代表日历的字符串。 |
import java.util.GregorianCalendar;public class Main { public static void main(String[] args) { /*GregorianCalendar*/ GregorianCalendar gcalendar = new GregorianCalendar();//默认本地时间和时区 System.out.println("当前时间:"+gcalendar.getTime()); System.out.println("是否闰年:"+gcalendar.isLeapYear(2024)); }}
3.9.6 Stream & File & IO
Java.io 包通过数据流、序列化和文件系统为系统输入和输出提供类
3.9.6.1 控制台输入/输出
读取控制台输入
Java 的控制台输入由 System.in 完成。
为了获得一个绑定到控制台的字符流,你可以把 System.in 包装在一个 BufferedReader 对象中来创建一个字符流
BufferedReader语法:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
从控制台读取多字符输入
从 BufferedReader 对象读取一个字符要使用 read() 方法,其语法为:
int read( ) throws IOException
每次调用 read() 方法,它从输入流读取一个字符并把该字符作为整数值返回,当流结束的时候返回 -1,该方法抛出 IOException
从控制台读取字符串
从标准输入读取一个字符串需要使用 BufferedReader 的 readLine() 方法:语法为:
String readLine( ) throws IOException
代码实例:
import java.io.*;public class Main { public static void main(String[] args) throws IOException { /*读取控制台输入*/ char c; //使用 System.in创建 BufferedReader BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.println("输入字符, 按下 'q' 键退出。"); //读取多字符 do{ c = (char) br.read(); System.out.println(c); } while (c!='q'); System.out.println("读取多字符结束"); //读取字符串 BufferedReader brStr = new BufferedReader(new InputStreamReader(System.in)); String str; System.out.println("输入一行字符串文本"); System.out.println("输入 'end' 退出"); do { str = br.readLine(); System.out.println(str); } while (!str.equals("end")); System.out.println("读取字符串结束"); }}
执行示例
控制台输出
控制台的输出由 print( ) 和 println() 完成。这些方法都由类 PrintStream 定义,System.out 是该类对象的一个引用。
PrintStream 继承了 OutputStream类,并且实现了方法 write()。这样,write() 也可以用来往控制台写操作。
PrintStream 定义 write() 的最简单格式如下所示:
void write(int byteval)
该方法将 byteval 的低八位字节写到流中
注意:write() 方法不经常使用,因为 print() 和 println() 方法用起来更为方便
public class Main { public static void main(String[] args) { /*控制台输出*/ int b; b = 'A'; System.out.write(b); System.out.write('\n'); }}
3.9.6.2 读写文件
一个流被定义为一个数据序列。输入流用于从源读取数据,输出流用于向目标写数据。
下图是一个描述输入流和输出流的类层次图。
读写文件,我们主要使用FileInputStream 和 FileOutputStream,java.io 包中的 File 文件类允许我们处理文件
FileInputStream
该流用于从文件读取数据,它的对象可以用关键字 new 来创建。
有多种构造方法可用来创建对象。
使用字符串类型的文件名来创建一个输入流对象来读取文件:
InputStream f = new FileInputStream("C:/java/hello");
使用一个文件对象来创建一个输入流对象来读取文件。我们首先得使用 File() 方法来创建一个文件对象:
File f = new File("C:/java/hello");InputStream in = new FileInputStream(f);
InputStream 方法及描述
方法 | 描述 |
public void close() throws IOException{} | 关闭此文件输入流并释放与此流有关的所有系统资源。抛出IOException异常。 |
protected void finalize()throws IOException {} | 这个方法清除与该文件的连接。确保在不再引用文件输入流时调用其 close 方法。抛出IOException异常。 |
public int read(int r)throws IOException{} | 这个方法从 InputStream 对象读取指定字节的数据。返回为整数值。返回下一字节数据,如果已经到结尾则返回-1。 |
public int read(byte[] r) throws IOException{} | 这个方法从输入流读取r.length长度的字节。返回读取的字节数。如果是文件结尾则返回-1。 |
public int available() throws IOException{} | 返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取的字节数。返回一个整数值。 |
注:除了InputStream外还包括DataInputStream、 ByteArrayInputStream
import java.io.*;import java.nio.charset.StandardCharsets;public class Main { public static void main(String[] args) { /*FileInputStream try catch容错必须要有*/ try{ InputStream fis = new FileInputStream("D:/Java.txt"); int size=fis.available(); byte[] buffer=new byte[size]; //读取txt内容并输出字符串 int readResult=fis.read(buffer); String content = new String(buffer, StandardCharsets.UTF_8); fis.close(); System.out.println(content); } catch (Exception ex){ System.out.println(String.format("错误:%s",ex.getMessage())); } }}
FileOutputStream
该类用来创建一个文件并向文件中写数据。
如果该流在打开文件进行输出前,目标文件不存在,那么该流会创建该文件。
有两个构造方法可以用来创建 FileOutputStream 对象。
使用字符串类型的文件名来创建一个输出流对象:
OutputStream f = new FileOutputStream("C:/java/hello")
使用一个文件对象来创建一个输出流来写文件。我们首先得使用File()方法来创建一个文件对象:
File f = new File("C:/java/hello");OutputStream fOut = new FileOutputStream(f);
OutputStream方法及描述
方法 | 描述 |
public void close() throws IOException{} | 关闭此文件输入流并释放与此流有关的所有系统资源。抛出IOException异常。 |
protected void finalize()throws IOException {} | 这个方法清除与该文件的连接。确保在不再引用文件输入流时调用其 close 方法。抛出IOException异常。 |
public void write(int w)throws IOException{} | 这个方法把指定的字节写到输出流中。 |
public void write(byte[] w) | 把指定数组中w.length长度的字节写到OutputStream中。 |
注:除了OutputStream外还包括DataOutputStream、 ByteArrayOutputStream
import java.io.*;import java.nio.charset.StandardCharsets;public class Main { public static void main(String[] args) { /*FileOutputStream try catch容错必须*/ try{ String strPath="D:/MyJava.txt"; OutputStream os = new FileOutputStream(strPath); //写入内容 StringBuilder sb=new StringBuilder(); sb.append("Java是一种流行的编程语言,创建于1995年。\r\n"); sb.append("它是一种非常流行的语言,尽管它已经很老了。\r\n"); sb.append("它归甲骨文所有,现有30多亿台设备运行Java。\r\n"); os.write(sb.toString().getBytes()); os.close(); //读取内容 InputStream fis=new FileInputStream(strPath); int size=fis.available(); byte[] buffer=new byte[size]; //读取txt内容并输出字符串 int readResult=fis.read(buffer); String content = new String(buffer, StandardCharsets.UTF_8); fis.close(); System.out.println(content); } catch (Exception ex){ System.out.println(String.format("错误:%s",ex.getMessage())); } }}
读写文件除了FileInputStream 和FileOutStream,我们还可以通过File类来实现,java.io 包中的 File 文件类允许我们处理文件。
File类基础方法及描述
方法 | 类型 | 描述 |
canRead() | Boolean | 测试文件是否可读 |
canWrite() | Boolean | 测试文件是否可写 |
createNewFile() | Boolean | 创建一个空文件 |
delete() | Boolean | 删除文件 |
exists() | Boolean | 测试文件是否存在 |
getName() | String | 返回文件名 |
getAbsolutePath() | String | 返回文件的绝对路径名 |
length() | Long | 返回文件的大小(以字节为单位) |
list() | String[] | 返回目录中文件的数组 |
mkdir() | Boolean | 创建目录 |
import java.io.*;public class Main { public static void main(String[] args) { /*File类*/ try{ String strPath="D:/HelloJava.txt"; File myFile = new File(strPath); //如果文件不存在则创建文件 if(!myFile.exists()){ boolean isCreate= myFile.createNewFile(); } //写入内容 StringBuilder sb=new StringBuilder(); sb.append("Java是一种流行的编程语言,创建于1995年。\r\n"); sb.append("它是一种非常流行的语言,尽管它已经很老了。\r\n"); sb.append("它归甲骨文所有,现有30多亿台设备运行Java。\r\n"); FileWriter fw=new FileWriter(strPath,false); fw.write(sb.toString()); fw.close(); //读取内容 FileReader fr=new FileReader(strPath); BufferedReader br=new BufferedReader(fr); StringBuilder sb2=new StringBuilder(); String line; while ((line=br.readLine())!=null){ sb2.append(line+"\r\n"); } fr.close(); System.out.println(sb2.toString()); //删除文件 String fileName=myFile.getName(); boolean isDelete=myFile.delete(); if(isDelete){ System.out.printf("文件%s已删除",fileName); } else { System.out.printf("文件%s删除失败",fileName); } } catch (Exception ex){ System.out.printf("错误:%s",ex.getMessage()); } }}
3.9.7 Scanner 类
java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入。
下面是创建 Scanner 对象的基本语法:
Scanner s = new Scanner(System.in);
读取输入的字符串,通过next()和nextLine()方法
next():
1、一定要读取到有效字符后才可以结束输入。
2、对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
4、next() 不能得到带有空格的字符串。
nextLine():
1、以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
2、可以获得空白。
判断是否还有输入的数据,通过hasNext() 与 hasNextLine();如果要输入 int 或 float 类型的数据,在 Scanner 类中也有支持,但是在输入之前最好先使用 hasNextXxx() 方法进行验证,再使用 nextXxx() 来读取
Scanner读取输入的字符串:
import java.io.*;import java.util.Scanner;public class Main { public static void main(String[] args) { /*Scanner类*/ try{ //读取输入的内容,从键盘接收数据 Scanner sc=new Scanner(System.in); System.out.println("next方式接收:"); if(sc.hasNext()){ String dataTxt=sc.next(); System.out.println("输入的内容为:"+dataTxt); } sc.close(); } catch (Exception ex){ System.out.printf("错误:%s",ex.getMessage()); } }}
Scanner读取输入的整数:
import java.io.*;import java.util.Scanner;public class Main { public static void main(String[] args) { /*Scanner类*/ try{ //读取输入的内容,从键盘接收数据 int Scanner sc=new Scanner(System.in); System.out.println("next方式接收输入的整数"); int i = 0; System.out.print("输入整数:"); if(sc.hasNextInt()){ i = sc.nextInt();// 判断输入的是否是整数 System.out.println("整数数据:" + i);// 接收整数 } else { System.out.println("输入的不是整数!"); } sc.close(); } catch (Exception ex){ System.out.printf("错误:%s",ex.getMessage()); } }}
Scanner读取输入的小数:
import java.io.*;import java.util.Scanner;public class Main { public static void main(String[] args) { /*Scanner类*/ try{ //读取输入的内容,从键盘接收数据 float Scanner sc=new Scanner(System.in); System.out.println("next方式接收输入的小数"); float i = 0; System.out.println("输入小数:"); if(sc.hasNextFloat()){ i = sc.nextFloat();// 判断输入的是否是小数 System.out.println("小数数据:" + i);// 接收小数 } else { System.out.println("输入的不是小数!"); } sc.close(); } catch (Exception ex){ System.out.printf("错误:%s",ex.getMessage()); } }}
Scanner读取txt文本文档 内容:
import java.io.*;import java.util.Scanner;public class Main { public static void main(String[] args) { /*Scanner类*/ try{ //Scan读取txt内容 FileReader fr=new FileReader("D:/HelloJava.txt"); Scanner myReader = new Scanner(fr); //如果下一行有数据,那么获取下一行内容 StringBuilder sb=new StringBuilder(); while (myReader.hasNextLine()) { String data = myReader.nextLine(); sb.append(data+"\r\n"); } myReader.close(); fr.close(); System.out.println(sb.toString()); } catch (Exception ex){ System.out.printf("错误:%s",ex.getMessage()); } }}
3.9.8 正则表达式
Java 没有内置的正则表达式类,但我们可以导入 java.util.regex 包来使用正则表达式。该软件包包括以下类:
Pattern 类 - 定义模式(用于搜索):pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
Matcher 类 - 用于搜索模式:Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
PatternSyntaxException 类 - 指示正则表达式模式中的语法错误:PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
import java.util.regex.*;public class Main { public static void main(String[] args) { /*正则表达式*/ String content = "Hello java"; String pattern = ".*java.*"; boolean isMatch = Pattern.matches(pattern, content); System.out.println("字符串中是否包含了 'java' 子字符串:" + isMatch); }}
正则表达式模式—括号用于查找一系列字符:
表达式 | 描述 |
[abc] | 从括号内的选项中查找一个字符 |
[^abc] | 找到一个不在括号内的字符 |
[0-9] | 从 0 到 9 范围内查找一个字符 |
元字符—元字符是具有特殊含义的字符:
元字符 | 描述 |
| | 查找由 | 分隔的任意一种模式的匹配项如: cat|dog|fish |
. | 只查找任何字符的一个实例 |
^ | 查找作为字符串开头的匹配项,如: ^Hello |
$ | 在字符串末尾查找匹配项,如: World$ |
\d | 找一个数字 |
\s | 查找空白字符 |
\b | 在这样的单词开头查找匹配项: \bWORD,或在这样的单词结尾处查找匹配项: WORD\b |
\uxxxx | 查找十六进制数 xxxx 指定的 Unicode 字符 |
量词—量词定义数量:
量词 | 描述 |
n+ | 匹配任何至少包含一个 n 的字符串 |
n* | 匹配包含零次或多次出现 n 的任何字符串 |
n? | 匹配包含零次或一次出现 n 的任何字符串 |
n{x} | 匹配任何包含一系列 X n 的字符串 |
n{x,y} | 匹配任何包含 X 到 Y n 序列的字符串 |
n{x,} | 匹配任何包含至少 X n 的序列的字符串 |
注:如果您的表达式需要搜索其中一个特殊字符,您可以使用反斜杠 (\) 对其进行转义。在Java中,字符串中的反斜杠需要自己转义,所以需要两个反斜杠来转义特殊字符。例如,要搜索一个或多个问号,您可以使用以下表达式:"\\?"
4.0 方法
什么是方法:方法是一个代码块,只在运行时调用。可以将数据(称为参数)传递到方法中。方法用于执行某些操作,它们也称为函数。
方法的优点:
使程序变得更简短而清晰有利于程序维护可以提高程序开发的效率提高了代码的重用性方法命名规则:
方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头写,不使用连接符。例如:addPerson。下划线可能出现在 JUnit 测试方法名称中用以分隔名称的逻辑组件。一个典型的模式是:test<MethodUnderTest>_<state>,例如 testPop_emptyStack。方法的语法:
修饰符 返回值类型 方法名(参数类型 参数名){ ... 方法体 ... return 返回值;}
方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。返回值类型 :方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。方法名:是方法的实际名称。方法名和参数表共同构成方法签名。参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。方法体:方法体包含具体的语句,定义该方法的功能。4.0.1 方法定义及调用
要在Java中调用一个方法,请编写该方法的名称,后跟两个括号()和。
Java 支持两种调用方法的方式,根据方法是否返回值来选择。
当程序调用一个方法时,程序的控制权交给了被调用的方法。当被调用方法的返回语句执行或者到达方法体闭括号时候交还控制权给程序。
public class Main { public static void main(String[] args) { /*调用方法*/ SetName(); int sum=CalSum(2,5); System.out.println(sum); } /* 定义 void类型的无返回值,无参数的方法 * */ private static void SetName(){ String strName="Hello Java Method"; System.out.println(strName); } /*定义 int 类型的,带返回值,带参数的方法*/ private static int CalSum(int a,int b){ int sum=a+b; return sum; }}
4.0.2 方法的重载
多个方法可以具有相同的名称和不同的参数
public class Main { public static void main(String[] args) { /*调用方法-方法重载*/ CalSum(); int sum=CalSum(2,5); System.out.println(sum); int sum1=CalSum(2,5,3); System.out.println(sum1); float sum2=CalSum(1.56f,3.25f); System.out.println(sum2); } /* 定义 void类型的无返回值,无参数的方法 * */ private static void CalSum(){ int a=10; int b=30; System.out.println((a+b)); } /*计算并返回两个数字之和*/ private static int CalSum(int a,int b){ int sum=a+b; return sum; } /*计算并返回三个数字之和*/ private static int CalSum(int a,int b,int c){ int sum=a+b+c; return sum; } /*计算并返回两个小数之和*/ private static float CalSum(float a,float b){ float sum=a+b; return sum; }}
4.0.3 可变参数
可变参数的定义语法:
typeName... parameterName
public class Main { public static void main(String[] args) { /*调用方法-可变参数*/ int sum=CalSum(2,5,3,6,7); System.out.println(sum); int sum1=CalSum(new int[]{10,20,30,40}); System.out.println(sum1); } /*计算数字之和*/ private static int CalSum(int...numbers){ int sum=0; for (int i=0;i<numbers.length;i++){ sum+=numbers[i]; } return sum; }}
4.0.4 构造方法
当一个对象被创建时候,构造方法用来初始化该对象。构造方法和它所在类的名字相同,但构造方法没有返回值。
通常会使用构造方法给一个类的实例变量赋初值,或者执行其它必要的步骤来创建一个完整的对象。
不管你是否自定义构造方法,所有的类都有构造方法,因为 Java 自动提供了一个默认构造方法,默认构造方法的访问修饰符和类的访问修饰符相同(类为 public,构造函数也为 public;类改为 protected,构造函数也改为 protected)。
一旦你定义了自己的构造方法,默认构造方法就会失效。
/*学生信息类*/public class StudentInfo { long id; //构造方法 StudentInfo(){ id=20240813l; }}
4.1 异常处理
异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。
异常发生的原因有很多,通常包含以下几大类:
这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。
要理解 Java 异常处理是如何工作的,需要掌握以下三种类型的异常:
检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这些异常在编译时强制要求程序员处理。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。这类异常通常使用 try-catch 块来捕获并处理异常,或者在方法声明中使用 throws 子句声明方法可能抛出的异常。
try {
// 可能会抛出异常的代码
} catch (IOException e) {
// 处理异常的代码
}
或者
public void readFile() throws IOException {
// 可能会抛出IOException的代码
}
运行时异常: 这些异常在编译时不强制要求处理,通常是由程序中的错误引起的,例如 NullPointerException、ArrayIndexOutOfBoundsException 等,这类异常可以选择处理,但并非强制要求。
try {
// 可能会抛出异常的代码
} catch (NullPointerException e) {
// 处理异常的代码
}
错误: 错误不是异常,而是脱离程序员控制的问题,错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
Java 提供了以下关键字和类来支持异常处理:
try:用于包裹可能会抛出异常的代码块。
catch:用于捕获异常并处理异常的代码块。
finally:用于包含无论是否发生异常都需要执行的代码块。
throw:用于手动抛出异常。
throws:用于在方法声明中指定方法可能抛出的异常。
Exception类:是所有异常类的父类,它提供了一些方法来获取异常信息,如 getMessage()、printStackTrace() 等。
4.1.1 Exception 类的层次
所有的异常类是从 java.lang.Exception 类继承的子类。
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。
Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。
Error 用来指示运行时环境发生的错误。
4.1.2 Java 内置异常类
Java 语言定义了一些异常类在 java.lang 标准包中。
标准运行时异常类的子类是最常见的异常类。由于 java.lang 包是默认加载到所有的 Java 程序的,所以大部分从运行时异常类继承而来的异常都可以直接使用。
非检查性异常:
异常 | 描述 |
ArithmeticException | 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。 |
ArrayIndexOutOfBoundsException | 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。 |
ArrayStoreException | 试图将错误类型的对象存储到一个对象数组时抛出的异常。 |
ClassCastException | 当试图将对象强制转换为不是实例的子类时,抛出该异常。 |
IllegalArgumentException | 抛出的异常表明向方法传递了一个不合法或不正确的参数。 |
IllegalMonitorStateException | 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。 |
IllegalStateException | 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。 |
IllegalThreadStateException | 线程没有处于请求操作所要求的适当状态时抛出的异常。 |
IndexOutOfBoundsException | 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 |
NegativeArraySizeException | 如果应用程序试图创建大小为负的数组,则抛出该异常。 |
NullPointerException | 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 |
NumberFormatException | 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。 |
SecurityException | 由安全管理器抛出的异常,指示存在安全侵犯。 |
StringIndexOutOfBoundsException | 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。 |
UnsupportedOperationException | 当不支持请求的操作时,抛出该异常。 |
检查性异常类:
异常 | 描述 |
ClassNotFoundException | 应用程序试图加载类时,找不到相应的类,抛出该异常。 |
CloneNotSupportedException | 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。 |
IllegalAccessException | 拒绝访问一个类的时候,抛出该异常。 |
InstantiationException | 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。 |
InterruptedException | 一个线程被另一个线程中断,抛出该异常。 |
NoSuchFieldException | 请求的变量不存在 |
NoSuchMethodException | 请求的方法不存在 |
4.1.3 异常方法
方法 | 说明 |
public String getMessage() | 返回关于发生的异常的详细信息。这个消息Throwable 类的构造函数中初始化了。 |
public Throwable getCause() | 返回一个 Throwable 对象代表异常原因。 |
public String toString() | 返回此 Throwable 的简短描述。 |
public void printStackTrace() | 将此 Throwable 及其回溯打印到标准错误流。 |
public StackTraceElement [] getStackTrace() | 返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。 |
public Throwable fillInStackTrace() | 用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。 |
4.1.4 捕获异常
try/catch 的语法:
try
{
// 程序代码
}catch(ExceptionName e1)
{
//Catch 块
}
public class Main { public static void main(String[] args) { /*异常捕获*/ try{ int[] inta={1,2}; System.out.println(inta[2]); } catch (ArrayIndexOutOfBoundsException ex){ System.out.println("错误 :" + ex); } }}
异常多重捕获的语法:
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型3 异常的变量名3){
// 程序代码
}
可以在 try 语句后面添加任意数量的 catch 块。
如果保护代码中发生异常,异常被抛给第一个 catch 块。
如果抛出异常的数据类型与 ExceptionType1 匹配,它在这里就会被捕获。
如果不匹配,它会被传递给第二个 catch 块。
如此,直到异常被捕获或者通过所有的 catch 块。
import java.io.*;public class Main { public static void main(String[] args) { /*异常捕获*/ try{ var file= new FileInputStream("D:/MyJava.txt"); var bytex=(byte)file.read(); } catch (FileNotFoundException ex){ System.out.println("文件不存在:"+ex.getMessage()); } catch (IOException ioex){ System.out.println("文件读取错误:" + ioex); } }}
throws/throw 关键字:throw 关键字用于在代码中抛出异常,而 throws 关键字用于在方法声明中指定可能会抛出的异常类型。
import java.io.*;public class Main { public static void main(String[] args) { /*异常捕获*/ int num=-1; if (num < 0) { throw new IllegalArgumentException("数字必须为正整数"); } } public void readFile() throws IOException { String filePath="D:/MyJava.txt"; BufferedReader reader = new BufferedReader(new FileReader(filePath)); String line = reader.readLine(); while (line != null) { System.out.println(line); line = reader.readLine(); } reader.close(); }}
finally关键字:
finally 关键字用来创建在 try 代码块后面执行的代码块。
无论是否发生异常,finally 代码块中的代码总会被执行。
在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。
finally 代码块出现在 catch 代码块最后,语法如下:
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 程序代码
}
注意事项:
catch 不能独立于 try 存在在 try/catch 后面添加 finally 块并非强制性要求的try 代码后不能既没 catch 块也没 finally 块try, catch, finally 块之间不能添加任何代码public class Main { public static void main(String[] args) { /*异常捕获*/ int a[] = {2,3,4}; try{ System.out.println("第三个元素 :" + a[3]); }catch(ArrayIndexOutOfBoundsException e){ System.out.println("Exception thrown :" + e); } finally{ a[0] = 6; System.out.println("第一个元素值: " +a[0]); System.out.println("finally 被执行"); } }}
try-with-resources:
JDK7 之后,Java 新增的 try-with-resource 语法结构,旨在自动管理资源,确保资源在使用后能够及时关闭,避免资源泄露 。
try-with-resources 是一种异常处理机制,它能够自动关闭在 try 块中声明的资源,无需显式地在 finally 块中关闭。
在 try-with-resources 语句中,你只需要在 try 关键字后面声明资源,然后跟随一个代码块。无论代码块中的操作是否成功,资源都会在 try 代码块执行完毕后自动关闭。
语法:
try (resource declaration) {
// 使用的资源
} catch (ExceptionType e1) {
// 异常块
}
注意:try-with-resources 语句关闭所有实现 AutoCloseable 接口的资源。
import java.util.Scanner;import java.io.*;public class Main { public static void main(String[] args) { /*异常捕获——try-with-resources*/ String line; try(BufferedReader br = new BufferedReader(new FileReader("D:/test.txt"))) { while ((line = br.readLine()) != null) { System.out.println("Line =>"+line); } } catch (IOException e) { System.out.println("IOException in try block =>" + e.getMessage()); } //try-with-resources 语句中可以声明多个资源,方法是使用分号 ; 分隔各个资源 try ( Scanner scanner = new Scanner(new File("D:/testRead.txt")); PrintWriter writer = new PrintWriter(new File("D:/testWrite.txt")) ) { while (scanner.hasNext()) { writer.print(scanner.nextLine()); } } catch (IOException e) { System.out.println("IOException in try block =>" + e.getMessage()); } }}
4.1.5 自定义异常
自定义异常注意事项:
所有异常都必须是 Throwable 的子类如果希望写一个检查性异常类,则需要继承 Exception 类如果你想写一个运行时异常类,那么需要继承 RuntimeException 类package my.java.study;//自定义异常类——继承Exceptionpublic class InsufficientFundsException extends Exception{ //此处的amount用来储存当出现异常(取出钱多于余额时)所缺乏的钱 private double amount; public InsufficientFundsException(double amount) { this.amount = amount; } public double getAmount() { return amount; }}
import my.java.study.*;public class Main { public static void main(String[] args) { /*异常捕获——自定义异常类*/ try{ withdraw(500,400); } catch (InsufficientFundsException e){ System.out.println("银行卡余额不足,还差 " + e.getAmount()+"元"); e.printStackTrace(); } } /* 取钱 amount:需要取的钱 balance:银行卡余额 * */ public static void withdraw(double amount,double balance) throws InsufficientFundsException { if(amount <= balance) { balance -= amount; } else { double needs = amount - balance; throw new InsufficientFundsException(needs); } }}
4.2 附录
官网学习:Dev.java: The Destination for Java Developers
java中文网:学习Java - java中文网
其他推荐学习网址:Java 教程 | 菜鸟教程 Java 教程_w3cschool
Java 教程