一、常用String类方法
-
public boolean equals(Object anObject):
"equals()"方法用于比较两个字符串的内容是否相同。它与 "==" 运算符不同,后者比较的是对象的引用。需要注意的是equals()在比较内容是否相同的时候是区分大小写的。
下面用代码演示一下:
public class EqualsExample {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello");
System.out.println(str1.equals(str2)); // true
System.out.println(str1.equals(str3)); // true
System.out.println(str1 == str2); // true
System.out.println(str1 == str3); // false
}
}
-
public boolean equalsIgnoreCase(String anotherString):
"equalsIgnoreCase()" 方法用于比较两个字符串的内容是否相同,忽略大小写差异。
下面是代码演示:
public class EqualsIgnoreCaseExample {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "hello";
System.out.println(str1.equalsIgnoreCase(str2)); // true
}
}
-
public char charAt(int index):
"charAt()" 方法用于返回指定索引处的字符。索引从 0 开始。一般用于寻找字符串中的单个字符所在的位置。
下面是代码演示:
public class CharAtExample {
public static void main(String[] args) {
String str = "Hello";
System.out.println(str.charAt(0)); // H
System.out.println(str.charAt(4)); // o
}
}
-
public char[] toCharArray():
"toCharArray()"方法可以将字符串转换为字符数组。可以用于遍历字符串的遍历。
下面是代码演示:
public class ToCharArrayExample {
public static void main(String[] args) {
String str = "Hello";
char[] charArray = str.toCharArray();
for (char c : charArray) {
System.out.print(c + " "); // H e l l o
}
}
}
-
public String substring(int beginIndex, int endIndex):
"substring()"方法用于返回一个新字符串,它是此字符串的一个子字符串。该子字符串从指定的 "beginIndex"处开始,到"endIndex - 1"处结束。
下面是代码演示:
public class SubstringExample {
public static void main(String[] args) {
String str = "Hello, World";
System.out.println(str.substring(0, 5)); // Hello
System.out.println(str.substring(7, 12)); // World
}
}
-
public String substring(int beginIndex) :
"substring()"方法用于返回一个新字符串,它是此字符串的一个子字符串,从指定的"beginIndex"处开始,直到字符串的结尾。
下面是代码演示:
public class SubstringBeginIndexExample {
public static void main(String[] args) {
String str = "Hello, World";
System.out.println(str.substring(7)); // World
}
}
-
public String replace(CharSequence target, CharSequence replacement):
"replace()"方法用于替换字符串中的指定字符或子字符串。
下面是代码的演示:
public class ReplaceExample {
public static void main(String[] args) {
String str = "Hello, World";
System.out.println(str.replace("World", "you")); // Hello, you
}
}
-
public String[] split(String regex):
"split()"根据传入的字符串作为规则进行切割将切割后的内容存入字符串数组中,并将字符串数组返回。
下面是代码演示:
public class SplitExample {
public static void main(String[] args) {
String str = "one,two,three";
String[] parts = str.split(",");
for (int i=0; i<parts.length; i++) {
System.out.println(parts[i]);
}
// 输出:
// one
// two
// three
}
}
二、String和StringBuilder、StringBuffer
(一)、String类:
1、常用的构造方法:
public String():创建一个空白字符串对象,不含有任何内容。
String str2 = new String();
public String(char[] chs):根据字符数组的内容,来创建字符串对象。
char[] charArray = {'H', 'e', 'l', 'l', 'o'};
String str3 = new String(charArray);
public String(String original):根据传入的字符串的内容,来创建字符串对象。
String str2 = new String("Hello, World");
或者
byte[] byteArray = {72, 110, 128, 188, 111};
String str4 = new String(byteArray);
也可以通过部分字符数组创建字符串:
char[] charArray = {'J', 'a', 'v', 'a', ' ', 'S', 't', 'r', 'i', 'n', 'g'};
String str5 = new String(charArray, 5, 6);
String s="abc";这是最常见的方式,通过字符串字面量直接创建字符串对象。
2、字符串的特点:
不可变性:"String" 对象是不可变的,一旦创建后,不能修改其内容。每次对字符串进行操作(如拼接、替换等)时,都会生成一个新的 "String"对象。
线程安全:由于 "String"对象是不可变的,因此是线程安全的,可以在多个线程之间安全地共享。
字符串常量池:所有字符串常量都会存在方法区的字符串常量池中,使用字符串字面量创建对象时,系统会检查该字符串是否在字符串常量池存在,如果不存在,会创建 ,如果存在,不会重新创建而是直接复用。
性能方面:由于不可变性,频繁的字符串拼接操作会生成大量的临时对象,导致性能下降。
3、创建字符串对象的区别对比:
通过构造方法创建:
通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同。
直接赋值方式创建:
以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象,并在字符串池中维护。
(二)、StringBuilder类:
概述:StringBuilder 是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是 StringBuilder 对象中的内容是可变的。
常用的构造方法:
public StringBuilder():创建一个空白可变字符串对象,不含有任何内容,称为默认构造方法,创建一个初始容量为 16 的字符串构建器。
StringBuilder sb = new StringBuilder();
这个还有一种方式是指定初始容量,称为指定初始容量的构造方法,创建一个具有指定初始容量的字符串构建器。
StringBuilder sb2 = new StringBuilder(50);
public StringBuilder(String str):根据字符串的内容,来创建可变字符串对象,称为通过字符串创建字符串构建器,创建一个包含指定字符串内容的字符串构建器。
StringBuilder sb2 = new StringBuilder("hello");
字符串的特点:
可变性:"StringBuilder"是可变的,可以对其内容进行修改,而不会像 `String` 那样每次操作都生成新的对象。
线程不安全:"StringBuilder"不是线程安全的。如果需要线程安全的可变字符序列,应该使用 "StringBuffer"类。
高效性:由于"StringBuilder"是可变的,因此在需要频繁修改字符串内容的场景中,比"String"更高效。
StringBuilder常用的成员方法:
"append"方法:用于在字符串的末尾追加内容。
StringBuilder sb = new StringBuilder("Hello");
sb.append(", World");
System.out.println(sb.toString());
"insert"方法:用于在指定位置插入内容。
StringBuilder sb = new StringBuilder("Hello");
sb.insert(5, ", World");
System.out.println(sb.toString());
"delete"方法:用于删除指定范围内的字符。
StringBuilder sb = new StringBuilder("Hello, World");
sb.delete(5, 7);
System.out.println(sb.toString());
"replace"方法:用于替换指定范围内的字符。
StringBuilder sb = new StringBuilder("Hello, World");
sb.replace(5, 7, "!");
System.out.println(sb.toString());
"reverse"方法:用于反转字符串。
StringBuilder sb = new StringBuilder("Hello");
sb.reverse();
System.out.println(sb.toString()); // 输出: olleH
**`toString` 方法**:将 `StringBuilder` 对象转换为 `String` 对象。
StringBuilder sb = new StringBuilder("Hello, World");
String str = sb.toString();
System.out.println(str);
StringBuilder和String相互转换:
StringBuilder转换为String:
public String toString():通过 toString() 就可以实现把 StringBuilder 转换为 String.
StringBuilder sb = new StringBuilder("Hello, World");
String str = sb.toString();
String转换为StringBuilder:
public StringBuilder(String s):通过构造方法就可以实现把 String 转换为 StringBuilder.
String str = "Hello, World";
StringBuilder sb = new StringBuilder(str);
(三)、StringBuffer类:
StringBuffer类的构造方法和StringBuilder相同,成员方法的使用也一样,这里就不过多介绍了。
下面主要介绍一下StringBuffer类的特点:
StringBuffer 是一个可变的字符序列,用于创建和操作字符串。它具有以下特点:
可变性:StringBuffer 对象可以在原对象上进行修改,而不需要生成新的对象,这使得它在需要频繁修改字符串的场景中更高效。
线程安全:StringBuffer 的所有方法都是同步的,因此它是线程安全的,适合在多线程环境中使用。不过,正因为线程安全,StringBuffer 的性能相对 StringBuilder 要低一些。
性能较优:尽管 StringBuffer 的性能不如 StringBuilder,但在多线程环境下,它依然比使用 String 类进行字符串操作要高效得多。
(四)、对比String和StringBuilder、StringBuffer:
1、String类:"String"类是不可变的字符序列,广泛用于表示和操作固定字符串。
特点
不可变性:一旦创建,字符串对象就不能修改。每次对字符串进行修改操作时,都会生成一个新的字符串对象。
线程安全:由于不可变性,`String` 对象是线程安全的。
字符串池:Java 使用字符串池来缓存常量字符串,以提高性能和减少内存使用。
适用场景
适用于字符串内容不需要频繁修改的场景。
适用于需要线程安全且不可变的字符串数据。
2、StringBuilder类:"StringBuilder"是一个可变的字符序列,用于高效地构建和修改字符串内容。
特点
可变性:可以在原对象上进行修改,而不需要生成新的对象。
非线程安全:`StringBuilder` 的方法不是同步的,因此不是线程安全的。
性能高效:由于没有线程安全的开销,在单线程环境中性能优于 `StringBuffer`。
适用场景
适用于单线程环境中需要频繁修改字符串的场景。
适用于构建长字符串,例如使用循环构建动态内容。
3、StringBuffer 类:"StringBuffer"也是一个可变的字符序列,与"StringBuilder"类似,但它是线程安全的。
特点
可变性:可以在原对象上进行修改,而不需要生成新的对象。
线程安全:"StringBuffer" 的方法是同步的,因此是线程安全的。
性能较高:在多线程环境中,"StringBuffer"提供了高效的字符串修改操作。
适用场景
适用于多线程环境中需要频繁修改字符串的场景。
适用于需要线程安全的字符串操作。
4、对比总结:
可变性:
String:不可变。
StringBuilder和StringBuffer:可变。
线程安全性:
String和StringBuffer:线程安全。
StringBuilder:非线程安全。
性能:
String:在频繁修改场景中性能较差。
StringBuilder:在单线程环境中性能最佳。
StringBuffer:在多线程环境中性能较优。
5、如何选择:
使用String:
字符串内容不会改变。
需要线程安全的字符串数据。
使用StringBuilder:
在单线程环境中需要频繁修改字符串。
构建动态字符串,例如通过循环构建内容。
使用 StringBuffer:
在多线程环境中需要频繁修改字符串。
需要线程安全的字符串操作。
三、介绍包装类:
Java 提供了八种基本数据类型,如 "int"、"char"等,这些类型在编程中非常常用。然而,有时需要将基本数据类型转换为对象,以便在需要对象的场景中使用。这时候,包装类(Wrapper Class)就派上了用场。本文将介绍基本类型的包装类,并详细讨论 "Integer"类、"Character"类、自动拆箱与自动装箱以及 "int"和 "String"类型的相互转换。
(一)、基本类型包装类
Java 提供了以下八个包装类,对应于八种基本数据类型:
"boolean"对应 "Boolean"
"byte"对应 "Byte"
"short"对应 "Short"
"int"对应 "Integer"
"long"对应 "Long"
"float"对应 "Float"
"double"对应 "Double"
"char"对应 "Character"
包装类将基本数据类型封装为对象,从而提供了更多的功能,例如在集合框架中使用基本数据类型。
(二)、Integer类:
"Integer"类是 "int"类型的包装类,它封装了一个 "int"值,并提供了许多实用的方法。
Integer 类的常用方法:
1. "parseInt(String s)":将字符串转换为 "int"类型。
2. "valueOf(String s)":将字符串转换为 "Integer"对象。
3. "intValue()":返回 "Integer"对象的 "int"值。
代码演示:
public class IntegerExample {
public static void main(String[] args) {
// 将字符串转换为 int 类型
int num = Integer.parseInt("123");
System.out.println(num); // 输出 123
// 将字符串转换为 Integer 对象
Integer integerObject = Integer.valueOf("456");
System.out.println(integerObject); // 输出 456
// 获取 Integer 对象的 int 值
int intValue = integerObject.intValue();
System.out.println(intValue); // 输出 456
}
}
(三)、Character类:
"Character"类是 "char"类型的包装类,提供了许多用于处理单个字符的方法。
Character 类的常用方法:
1. "isLetter(char ch)":判断字符是否是字母。
2. "isDigit(char ch)":判断字符是否是数字。
3. "toUpperCase(char ch)":将字符转换为大写。
4. "toLowerCase(char ch)":将字符转换为小写。
代码演示:
public class CharacterExample {
public static void main(String[] args) {
char ch = 'a';
// 判断是否是字母
System.out.println(Character.isLetter(ch)); // 输出 true
// 判断是否是数字
System.out.println(Character.isDigit(ch)); // 输出 false
// 转换为大写
System.out.println(Character.toUpperCase(ch)); // 输出 A
// 转换为小写
System.out.println(Character.toLowerCase('A')); // 输出 a
}
}
(四)、自动拆箱和自动装箱:
自动装箱:把基本数据类型转换为对应的包装类类型。
自动拆箱:把包装类类型转换为对应的基本数据类型。
public class AutoboxingUnboxingExample {
public static void main(String[] args) {
// 自动装箱
Integer integerObject = 26;
// 自动拆箱
int num = integerObject;
System.out.println(integerObject); // 输出 26
System.out.println(num); // 输出 26
}
}
(五)、int和String类型的相互转换:
int转换为String:
方式一:直接在数字后加一个空字符串:
int num = 123;
String str=123+" ";
方式二:通过String类静态方法valueOf():
int num = 123;
String str = String.valueOf(num);
System.out.println(str);
方式三、使用 "Integer.toString(int i)"方法:
int num = 123;
String str = Integer.toString(num);
System.out.println(str);
String 转 int:
方式一:先将字符串数字转成Integer,再调用valueOf()方法:
String str = "123";
int num = Integer.valueOf(str);
System.out.println(num);
方式二:通过Integer静态方法parseInt()进行转换:
String str = "123";
int num = Integer.parseInt(str);
System.out.println(num);
四、时间日期类
(一)、Date类:
Date类是 Java 中最早用于表示日期和时间的类。它提供了表示时间点的功能,但其设计较为简单,缺乏对日期和时间的详细操作支持。随着 Java 的发展,Date类逐渐被其他更强大的日期时间类所替代,但它仍然在某些场景中使用。
Date类构造方法:
public Date()分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒。表示的是当前系统的时间。
Date date = new Date();
public Date(long date)分配一个 Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数。表示的是这个时间距离计算机原点时间多少ms的那个时间(原点时间是会自动计算时区的,比如:中国:东八区,加八小时)。
long date = 1000*60*60;
Date d2 = new Date(date);
Date类常用方法:
public long getTime()获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值:
Date date = new Date();long time1=date.getTime();
public void setTime(long time)设置时间,给的是毫秒值:
long time2=System.currentTimeMillis();date.setTime(time2);
(二)、SimpleDateFormat:
SimpleDateFormat类概述:
SimpleDateFormat是一个具体的类,用于以区域设置敏感的方式格式化和解析日期。
格式化是指时间对象---->时间字符串,解析是指时间字符串------>时间对象。
SimpleDateFormat类构造方法:
public SimpleDateFormat()构造一个SimpleDateFormat,使用默认模式和日期格式。
SimpleDateFormat sdf = new SimpleDateFormat();
public SimpleDateFormat(String pattern)构造一个SimpleDateFormat使用给定的模式和默认的日期格式。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
SimpleDateFormat类的常用方法:
格式化(从Date到String):public final String format(Date date):将日期格式化成日期/时间字符串。
//格式化:从 Date 到 String
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String s = sdf.format(d);
解析(从String到Date):public Date parse(String source):从给定字符串的开始解析文本以生成日期。
注意的是生成对象时里面的格式要和字符串的相同。
//从 String 到 Date
String ss = "2048-08-09 11:11:11";
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dd = sdf2.parse(ss);
(三)、 LocalDateTime:
LocalDateTime 类是 Java 8 引入的新的日期时间 API 的一部分,它是一个不可变的日期时间对象,表示日期和时间(不包含时区信息)。它提供了丰富的方法来操作日期和时间,并且线程安全。
LocalDateTime创建方法:
public static LocalDateTime now()获取当前系统时间。
LocalDateTime now = LocalDateTime.now();
public static LocalDateTime of (年, 月 , 日, 时, 分, 秒)使用指定年月日和时分秒初始化一个LocalDateTime对象:
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 11, 11, 11);
LocalDateTime获取方法:
public int getYear() | 获取年 |
public int getMonthValue() | 获取月份(1-12) |
public int getDayOfMonth() | 获取月份中的第几天(1-31) |
public int getDayOfYear() | 获取一年中的第几天(1-366) |
public DayOfWeek getDayOfWeek() | 获取星期 |
public int getMinute() | 获取分钟 |
public int getHour() | 获取小时 |
public class JDK8DateDemo3 {
public static void main(String[] args) {
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 11, 11, 20);
//public int getYear() 获取年
int year = localDateTime.getYear();
System.out.println("年为" +year);
//public int getMonthValue() 获取月份(1-12)
int month = localDateTime.getMonthValue();
System.out.println("月份为" + month);
Month month1 = localDateTime.getMonth();
// System.out.println(month1);
//public int getDayOfMonth() 获取月份中的第几天(1-31)
int day = localDateTime.getDayOfMonth();
System.out.println("日期为" + day);
//public int getDayOfYear() 获取一年中的第几天(1-366)
int dayOfYear = localDateTime.getDayOfYear();
System.out.println("这是一年中的第" + dayOfYear + "天");
//public DayOfWeek getDayOfWeek()获取星期
DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();
System.out.println("星期为" + dayOfWeek);
//public int getMinute() 获取分钟
int minute = localDateTime.getMinute();
System.out.println("分钟为" + minute);
//public int getHour() 获取小时
int hour = localDateTime.getHour();
System.out.println("小时为" + hour);
}
}
LocalDateTime转换方法:
public LocalDate toLocalDate ()转换成为一个LocalDate对象:
LocalDate localDate = localDateTime.toLocalDate();
public LocalTime toLocalTime ()转换成为一个LocalTime对象:
LocalTime localTime = localDateTime.toLocalTime();
LocalDateTime格式化和解析:
public String format (指定格式)把一个LocalDateTime格式化成为一个字符串:
String s = localDateTime.format(pattern);
public LocalDateTime parse (准备解析的字符串, 解析格式)把一个日期字符串解析成为一个LocalDateTime对象:
String s = "2020年11月12日 13:14:15";
DateTimeFormatter pattern =DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
LocalDateTime parse = LocalDateTime.parse(s, pattern);
public static DateTimeFormatter ofPattern(String pattern)使用指定的日期模板获取一个日期格式化器DateTimeFormatter对象:
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
LocalDateTime增加或者减少时间的方法:
方法名 | 说明 |
---|---|
public LocalDateTime plusYears (long years) | 添加或者减去年 |
public LocalDateTime plusMonths(long months) | 添加或者减去月 |
public LocalDateTime plusDays(long days) | 添加或者减去日 |
public LocalDateTime plusHours(long hours) | 添加或者减去时 |
public LocalDateTime plusMinutes(long minutes) | 添加或者减去分 |
public LocalDateTime plusSeconds(long seconds) | 添加或者减去秒 |
public LocalDateTime plusWeeks(long weeks) | 添加或者减去周 |
方法名 | 说明 |
---|---|
public LocalDateTime minusYears (long years) | 减去或者添加年 |
public LocalDateTime minusMonths(long months) | 减去或者添加月 |
public LocalDateTime minusDays(long days) | 减去或者添加日 |
public LocalDateTime minusHours(long hours) | 减去或者添加时 |
public LocalDateTime minusMinutes(long minutes) | 减去或者添加分 |
public LocalDateTime minusSeconds(long seconds) | 减去或者添加秒 |
public LocalDateTime minusWeeks(long weeks) | 减去或者添加周 |
LocalDateTime修改方法:
方法名 | 说明 |
---|---|
public LocalDateTime withYear(int year) | 直接修改年 |
public LocalDateTime withMonth(int month) | 直接修改月 |
public LocalDateTime withDayOfMonth(int dayofmonth) | 直接修改日期(一个月中的第几天) |
public LocalDateTime withDayOfYear(int dayOfYear) | 直接修改日期(一年中的第几天) |
public LocalDateTime withHour(int hour) | 直接修改小时 |
public LocalDateTime withMinute(int minute) | 直接修改分钟 |
public LocalDateTime withSecond(int second) | 直接修改秒 |
五、异常:
(一)、异常的介绍
-
异常的概述
异常就是程序出现了不正常的情况
-
异常的体系结构:
Throwable
Error(严重问题,通过代码无法处理。例如:内存溢出)
Exception(称为异常类,表示程序本身可以处理的问题)
RentimeException及其子类
这个异常是运行时异常。(空指针异常,数组索引越界异常)
除RentimeException之外所有的异常
这个是指编译期必须处理的,否则程序不能通过编译。(日期格式化异常)
编译时异常和运行时异常:
-
编译时异常
-
都是Exception类及其子类
-
必须显示处理,否则程序就会发生错误,无法通过编译
-
使用Javac.exe将Java文件转换为字节码文件时,就可能会出现编译时异常。所以编译时异常,是在编译成class文件时必须要处理的异常,也称之为受检异常。
-
-
运行时异常
-
都是RuntimeException类及其子类
-
无需显示处理,也可以和编译时异常一样处理
-
在字节码文件显示出运行结果时,可能就会出现运行时异常。所以运行时异常,是在编译成class文件时不需要处理,在运行字节码文件时可能出现的异常。也称之为非受检异常。
-
(二)、异常的处理方式
JVM处理异常的过程:
1 会在异常的位置生成一个异常类的对象new Exception()-->2 看程序是否有自己处理异常的代码,java中异常处理的两种方式:throws,try-catch-->3 如果有,则按照处理异常的逻辑处理,如果没有,它会交给方法的调用者来处理-->4 方法调用会依次传递给main方法,如果main依然没有处理,就抛给jvm来处理-->把异常的名称,错误原因及异常出现的位置等信息输出在了控制台-->程序停止执行。
异常处理的方式:
1、throws和throw方式:
throws:
throws关键字用于方法签名中,声明该方法可能抛出的异常。它告知调用该方法的代码需要处理这些可能的异常。
用法:
public void myMethod() throws IOException, SQLException {
// 可能抛出 IOException 或 SQLException 的代码
}
示例代码
以下示例展示了如何使用throws关键字声明方法可能抛出的异常:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ThrowsExample {
public static void main(String[] args) {
try {
readFile("example.txt");
} catch (IOException e) {
System.out.println("Caught IOException: " + e.getMessage());
}
}
public static void readFile(String fileName) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
}
在这个例子中,readFile方法声明它可能抛出IOException。在main方法中,调用readFile方法时必须处理这个异常。
throw:
throw关键字用于在方法体内显式地抛出一个异常。它创建一个异常对象并将其抛出,以通知调用者发生了异常情况。
用法:
public void myMethod(int age) {
if (age < 18) {
throw new IllegalArgumentException("Age must be at least 18");
}
// 其他代码
}
示例代码
以下示例展示了如何使用throw关键字显式抛出异常:
public class ThrowExample {
public static void main(String[] args) {
try {
validateAge(15);
} catch (IllegalArgumentException e) {
System.out.println("Caught IllegalArgumentException: " + e.getMessage());
}
}
public static void validateAge(int age) {
if (age < 18) {
throw new IllegalArgumentException("Age must be at least 18");
}
System.out.println("Age is valid");
}
}
在这个例子中,validateAge方法使用throw关键字显式抛出一个IllegalArgumentException,如果传入的年龄小于 18。在main方法中,调用validateAge方法时必须处理这个异常。
对比throws和throw:
用法位置:
throws:用于方法签名中,声明该方法可能抛出的异常类型。
throw:用于方法体内,显式地抛出一个异常对象。
作用:
throws:通知调用方法的代码,这个方法可能会抛出某些类型的异常,调用者需要处理这些异常。
throw:实际抛出一个异常,通知当前上下文发生了异常情况。
处理机制:
throws:由调用者决定如何处理声明的异常,可以选择捕获处理或继续向上抛出。
throw:立即抛出异常,并转移控制权到最近的异常处理块。
throws和throw结合使用:
在实际开发中,throws和throw经常结合使用,以实现完整的异常处理机制。以下是一个示例:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class CombinedExample {
public static void main(String[] args) {
try {
readFile("example.txt");
} catch (IOException e) {
System.out.println("Caught IOException: " + e.getMessage());
}
}
public static void readFile(String fileName) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
throw new IOException("Error reading file: " + fileName, e);
}
}
}
在这个示例中,readFile方法声明它可能抛出IOException,并在方法体内通过throw关键字显式抛出异常。如果读取文件时发生异常,它会抛出一个新的IOException,并附带原始异常作为原因。
2、try-catch方式:
try-catch 语句是异常处理的核心机制之一。它允许程序在遇到错误时捕获并处理异常,从而防止程序崩溃并提供用户友好的错误信息。
trycatch 的基本结构:
trycatch 语句块用于捕获和处理异常。基本结构如下:
try {
// 可能抛出异常的代码
} catch (ExceptionType1 e1) {
// 处理异常类型1
} catch (ExceptionType2 e2) {
// 处理异常类型2
} finally {
// 无论是否发生异常,都会执行的代码(可选)
}
说明:
try 块:包含可能抛出异常的代码。任何在此块中抛出的异常都将被相应的 catch 块捕获。
catch 块:用于捕获特定类型的异常,并进行处理。可以有多个 catch 块,每个处理不同类型的异常。
finally 块(可选):用于执行清理操作,无论是否发生异常都会执行,例如关闭文件、释放资源等。
以下示例展示了如何使用trycatch 语句处理异常:
public class TryCatchExample {
public static void main(String[] args) {
try {
int result = divide(10, 0);
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Caught ArithmeticException: " + e.getMessage());
} catch (Exception e) {
System.out.println("Caught Exception: " + e.getMessage());
} finally {
System.out.println("This will always be executed.");
}
}
public static int divide(int a, int b) {
return a / b;
}
}
在这个例子中,divide 方法在除数为 0 时抛出ArithmeticException。try 块捕获并处理了这个异常,而finally 块中的代码始终执行,即使发生了异常。
try-catch的注意事项:
try-catch方式中如果在try{}中没有出现问题,则会把try中所有的代码全部执行完毕,不会执行catch里面的代码。
如果在try中遇到了问题,那么会直接跳转到对应的catch语句中,try下面的代码就不会再执行了
当catch里面的语句全部执行完毕,表示整个体系全部执行完全,继续执行下面的代码。
如果出现的问题没有被捕获,那么try...catch就相当于没有写.那么也就是自己没有处理.默认交给虚拟机处理。
如果同时有可能出现多个异常,那么就写多个catch。如果多个异常之间存在子父类关系.那么父类一定要写在下面。
Throwable成员方法:
方法名 | 说明 |
---|---|
public String getMessage() | 返回此 throwable 的详细消息字符串 |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
(三)、自定义异常
概述:当Java中提供的异常不能满足我们的需求时,我们可以自定义异常。
实现步骤:
-
-
定义异常类
-
写继承关系
-
提供空参构造
-
提供带参构造
-