一、异常
1、异常体系
java.lang.Throwable类是 Java中所有错误或异常的超类- 常用方法
- public void printStackTrace():打印异常信息是最全的,包括异常类型、信息、以及出现的行数等
- public String toString() :输出异常类型和设置的异常信息
- public String getMessage():输出设置的异常信息
- 主要有两个子类
1)错误Error
- 错误
java.lang.Error: 无法处理的错误,只能事先避免。如java.lang.StackOverflowError、java.lang.OutOfMemoryError
2)异常Exception
- 异常
java.lang.Exception: 异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。又分为两类- 编译时异常:
java.lang.Exception包下除了RuntimeException之外的所有类- 没有任何的语法格式错误,但编译时JVM检查到存在安全隐患所报出的异常,如
FileNotFoundException、SQLException
- 没有任何的语法格式错误,但编译时JVM检查到存在安全隐患所报出的异常,如
- 运行时异常
java.lang.RuntimeException:编译时没有发生任何语法格式错误,在运行时出现了的异常,如NullPointerException、ClassCastException
- 编译时异常:
2、异常处理
- Java异常处理的5个关键字:try、catch、finally、throw、throws
- 使用场景
- 如果处理异常之后,还想让后续的代码正常执行,则使用
try...catch - 如果方法之间是递进关系(调用),我们可以先
throws,等到最后用try...catch做统一的异常处理
- 如果处理异常之后,还想让后续的代码正常执行,则使用
1)throws声明异常
- 将异常抛给调用者进行解决
- 在方法声明上使用throws关键字来声明异常,表示当前方法不处理异常,而是向上抛给调用者来处理
- 格式
修饰符 返回值类型 方法名 () throws 异常类名1,异常类名2,......,异常类名n {} - 注意
- 如果throws后的多个异常之间有子父类继承关系,我们可以直接throws父类异常
- 如果不知道多个异常之间是否有子父类继承关系,我们可以直接throws Exception
- 子类重写方法声明的异常类型不能大于父类方法的异常类型,可以相同、或者是其子异常或子类方法不声明异常
2)try…catch捕获异常
-
格式
try { 可能产生异常的代码 } catch(异常类型形参) { //catch可以有多个,当多个异常类型之间构成继承关系时,子类型必须放在父类型之前,或者只处理父异常 处理异常的代码 //如:记录日志/打印异常信息/继续抛出异常 } catch(异常类型形参) { 处理异常的代码 } finally { //finally中的代码总会执行,即使catch中也出现异常 //一般将资源关闭的代码放到finally代码块,因为有一些对象GC回收不了,需要我们手动关闭。如:连接对象,IO流对象,Socket对象 } -
在实际开发中,避免在catch里面出现return语句
public static int method (int num) { try { throw new IOException("IO异常"); } catch (IOException e) { e.printStackTrace(); return 3;// JVM本来要执行,在执行之前发现了finally,return暂缓执行 } finally { System.out.println("资源关闭"); return 4;//最终返回4 } }
3)手动抛出异常对象
-
throw new 异常类名() -
throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行
ServiceException tw = new ServiceException("abc");//创建异常对象不抛出不会报错 throw tw;//1.throw语句后不能直接跟语句,永远无法执行到; 2.如果抛出的是编译时异常,则编译报错,必选进行处理 System.out.println("这句永远执行不到,编译报错");
3、自定义异常类
- 自定义编译异常:继承Exception
- 自定义运行时异常:继承RuntimeException
- 提供有参构造方法,便于设置异常信息
二、常用类
1、Object
-
java.lang.Object类是Java语言中的根类,即所有类的父类 -
常用方法
/* toString()返回的是“对象的运行时类型 @ 对象的hashCode值的十六进制形式" 如果想输出对象的属性值,就重写Object中的toString方法 */ public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } /* 比较两个对象的地址值是否相等 == 针对于基本数据类型来说,比较的是值 == 针对于引用数据类型来说,比较的是地址值 如果想比较对象的属性值,就重写Object中的equals方法 */ public boolean equals(Object obj) { return (this == obj); } @IntrinsicCandidate public native int hashCode(); /* 复制一个属性值一样的新对象 需要被克隆的对象实现Cloneable接口并重写clone方法 */ @IntrinsicCandidate protected native Object clone() throws CloneNotSupportedException; //获取对象的运行时类型-见反射章节 @IntrinsicCandidate public final native Class<?> getClass(); //见多线程章节 @IntrinsicCandidate public final native void notify(); @IntrinsicCandidate public final native void notifyAll(); public final void wait() throws InterruptedException { wait(0L); } public final native void wait(long timeoutMillis) throws InterruptedException; public final void wait(long timeoutMillis, int nanos) throws InterruptedException { //... }
2、比较大小接口
1)java.lang.Comparable
-
基本类型数据需要比较大小,使用比较运算符即可
-
引用数据类型比较大小,可以实现
java.lang.Comparable接口,并重写compareTo方法public class Person implements Comparable<Person> { String name; int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } @Override public int compareTo(Person person) { //大于0,则当前对象大 //小于0,则当前对象小 //等于0,则两个对象相等 return this.age - person.age; } public static void main(String[] args) { Person p1 = new Person("张三", 18); Person p2 = new Person("王五", 20); System.out.println(p1.compareTo(p2)); // -2 } }
3)java.util.Comparator
-
使用场景:如果一个类没有实现Comparable接口,且又不方便修改源码;或者实现了Comparable接口,但不想按照它预定义的方法比较大小,又不能随意修改。可以使用
java.util.Comparator接口 -
创建比较器类:实现
java.util.Comparator接口,并重写方法import java.util.Comparator; public class Test01 { public static void main(String[] args) { int compare = new Comparator<Person>() { @Override public int compare(Person o1, Person o2) { return o1.getAge() - o2.getAge(); } }.compare(new Person("zhang3", 18), new Person("li4", 20)); System.out.println(compare); // -2 } }
3、字符串相关
1)java.lang.String
-
Java中所有字符串字面值(如 “abc” )都是此类的实例
-
字符串的对象是不可变对象,意味着一旦进行修改,就会产生新对象
-
jdk8中String底层是一个被final修饰的char数组
private final char[] value,一个char类型占2个字节 -
jdk9后String底层是一个被final修饰的byte数组
private final byte[] value,一个byte类型占1个字节 -
常用构造方法
String(); String(String original);//根据字符串创建String对象 String(char[] value);//根据char数组创建String对象 String(byte[] bytes);//通过使用操作系统的默认字符集解码指定的 byte 数组,构造一个新的 String //操作系统默认字符集:GBK,一个中文占2个字节;UTF-8,一个中文占3个字节 //Idea启动时可以指定默认字符集,如: -Dfile.encoding=UTF-8 //String 变量名 = ""//简化形式 -
常用方法
boolean equals(String s); boolean equalsIgnoreCase(String s); int length(); String concat(String s);// 字符串拼接,返回新串儿 char charAt(int index); // 根据索引获取对应的字符 int indexOf(String s); // 获取指定字符串在大字符串中第一次出现的索引位置 String subString(int beginIndex); // 截取字符串,从指定索引开始截取到最后,返回新串儿 String subString(int beginIndex,int endIndex); // 截取字符串,含头不含尾,返回新串儿 char[] toCharArray(); // 将字符串转成char数组 byte[] getBytes(); // 将字符串转成byte数组 byte[] getBytes(String charsetName); // 按照指定的编码 String replace(CharSequence c1,CharSequence c2); // 替换字符 String类实现了CharSequence接口 String[] split(String regex); //按照指定的规则分割字符串 regex写的是正则表达式 boolean contains(String s); boolean endsWith(String s); boolean startsWith(String s); String toLowerCase(); String toUpperCase(); String trim(); -
面试题
public static void main(String[] args) { String s1 = "HelloWorld"; String s2 = "HelloWorld"; String s3 = new String("HelloWorld"); String s4 = new String("HelloWorld"); String s5 = "Hello"; String s6 = "World"; System.out.println(s1==s2);//true 在常量池中创建,并指向同一地址 System.out.println(s1==s3);//false System.out.println(s2==s3);//false System.out.println(s3 == s4); // false System.out.println("============================"); /* 字符串拼接规则: 1.如果等号右边是字符串字面值拼接,不会产生新对象 2.如果等号右边有变量参数拼接,会产生新字符串对象 */ System.out.println(s1 == ("Hello" + "World")); //ture System.out.println(s1 == (s5 + "World")); // false System.out.println(s1 == (s5 + s6) ); //false System.out.println(s3 == (s5 + s6) ); //false }
2)java.lang.StringBuilder
- 一个可变的字符序列,不保证同步(线程不安全,但效率高)
- 作用:拼接字符串
- String每拼接一次,就会产生新的字符串对象,如果拼接次数多了,会占用内存,效率比较底
- StringBuilder底层自带缓冲区,拼接字符串之后都会在此缓冲区中保存,在拼接的过程中,不会随意产生新对象,节省内存
- 特点
- 底层自带缓冲区,此缓冲区是没有被final修饰的byte数组,默认长度为16
- 如果超出了数组长度,数组会自动扩容
- 默认每次扩容老数组的2倍+2,如果一次性添加的数据超出了默认的扩容数组长度(2倍+2),则以该数据长度扩容
- 常用方法
public StringBuilder append(任意类型数据)public StringBuilder reverse()字符串翻转public String toString()转为String后,可以使用String中的方法进行处理。而用StringBuilder拼接字符串是为了效率
3)java.lang.StringBuffer
- StringBuffer和StringBuilder的API基本一样(线程安全,效率低)
4、数字相关
1)java.lang.Math
-
final修饰的工具类,都是静态方法,私有构造方法,封装了基本的数学运算方法
-
常用方法
static int abs(xx a); static double ceil(xx a);// 向上取整 static double floor(xx a);// 向下取整 static long round(xx a);// 四舍五入 static int max(xx a, xx b); static int min(xx a, xx b); static double random();// 返回[0,1)的随机值
2)java.math.BigInteger
-
BigInteger类:处理比long还要大的整数
BigInteger(String val);// 参数的格式必须是数字形式 BigInteger add(BigInteger val); BigInteger subtract(BigInteger val); BigInteger multiply(BigInteger val); BigInteger divide(BigInteger val); BigInteger remainder(BigInteger val); int intValue();// 将BigInteger转成int long longValue();// 将BigInteger 转成 long
3)java.math.BigDecimal
-
BigDecimal类:主要是解决float和double直接做运算出现的精度损失问题,前提是构造要使用
new BigDecimal(String)BigDecimal(String val);// 参数的格式必须是数字形式 BigDecimal add(BigDecimal val); BigDecimal subtract(BigDecimal val); BigDecimal multiply(BigDecimal val); BigDecimal divide(BigDecimal val); /* divisor:除号后面的那个数 scale:指定保留几位小数 roundingMode:取舍方式 ROUND_UP 向上加1;ROUND_DOWN 直接舍去; ROUND_HALF_UP 四舍五入 */ BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode); BigDecimal remainder(BigDecimal val);
3)java.util.Random
-
public int nextInt(int n)在指定范围内随机生成一个整数,范围从[0,n)import java.util.Random; public class Test01 { public static void main(String[] args) { Random random = new Random(); //public System.out.println(random.nextInt(10));// 0-9 System.out.println(random.nextInt(10) + 1);// (0-9)+1 -> 1-10 System.out.println(random.nextInt(100) + 1);// (0-99)+1 -> 1-100 System.out.println(random.nextInt(900) + 100);// (0-899)+100 -> 100-999 } }
5、日期相关
1)java.util.Date
- 表示特定的瞬间,精确到毫秒
import java.util.Date;
public class Test01 {
public static void main(String[] args) {
//1、Date() -> 获取当前系统时间
Date date1 = new Date();
System.out.println("date1 = " + date1); //Sun Oct 19 13:45:43 CST 2025
//2、Date(long time) -> 根据毫秒值生成时间。毫秒值是从时间原点(1970年1月1日 0时0分0秒,UNIX系统起始时间)开始算,叫做格林威治时间,在0时区上
Date date2 = new Date(1000L);
System.out.println("date2 = " + date2);//Thu Jan 01 08:00:01 CST 1970
//1.void setTime(long time)
date1.setTime(3000L);
System.out.println("date1 = " + date1); //Thu Jan 01 08:00:03 CST 1970
//2.long getTime()
System.out.println(date2.getTime()); //1000
}
}
2)java.util.Calendar
- 日历类,抽象类
import java.util.Calendar;
import java.util.Date;
public class Test01 {
public static void main(String[] args) {
//1.Calendar getInstance() 通过Calendar的子类创建Calendar对象
Calendar calendar = Calendar.getInstance();
//2.int get(int field) ->返回给定日历字段的值
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
System.out.println("year = " + year); //year = 2025
System.out.println("month = " + month); //month = 9 注意:实际月份=9+1
//3.void set(int field, int value) :将给定的日历字段设置为指定的值
calendar.set(Calendar.YEAR,2018);
System.out.println(calendar.get(Calendar.YEAR)); //2018
//4.void add(int field, int amount) :根据日历的规则,为给定的日历字段添加或者减去指定的时间量
calendar.add(Calendar.YEAR,-1);
System.out.println(calendar.get(Calendar.YEAR)); //2017
//5.void set(int year, int month, int date) -> 直接设置年月日
calendar.set(2018,1,3);
//6.Date getTime():将Calendar转成Date对象
Date date = calendar.getTime();
System.out.println("date = " + date); //date = Sat Feb 03 13:56:36 CST 2018
}
}
3)java.text.SimpleDateFormat
- 可以将日期时间和字符串做转换
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//1.String format(Date date) -> 将Date对象按照指定的格式转成String
String time1 = sdf.format(new Date());
System.out.println("time1 = " + time1);
//2.Date parse(String source) throws ParseException-> 将符合日期格式的字符串转成Date对象
String time2 = "2018-2-3 1:2:3";
Date date = sdf.parse(time2);
System.out.println("date = " + date); //date = Sat Feb 03 01:02:03 CST 2018
}
6、日期相关(JDK1.8)
1)java.time.LocalDate、LocalTime、LocalDateTime
public static void main(String[] args) throws ParseException {
//1、创建LocalDate对象
LocalDate localDate = LocalDate.now();
System.out.println("localDate = " + localDate); //localDate = 2025-10-19
LocalDate localDate1 = LocalDate.of(2018, 1, 2); //localDate1 = 2018-01-02
System.out.println("localDate1 = " + localDate1);
//2、创建LocalDateTime对象
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("localDateTime = " + localDateTime);//localDateTime = 2025-10-19T15:21:55.283423200
LocalDateTime localDateTime1 = LocalDateTime.of(2018, 1, 2, 3, 4, 5);
System.out.println("localDateTime1 = " + localDateTime1); //localDateTime1 = 2018-01-02T03:04:05
// 3、获取年、月、日
System.out.println(localDate.getYear());//2025
System.out.println(localDate.getMonthValue());//10
System.out.println(localDate.getDayOfMonth());//19
// 4、修改年、月、日,支持链式调用
LocalDate localDate2 = localDate.withYear(2017).withMonth(2).withDayOfMonth(3);
System.out.println("localDate2 = " + localDate2); //localDate2 = 2017-02-03
// 5、设置日期字段的偏移量,方法名plus开头,向后偏移;方法名minus开头,向前偏移
LocalDate localDate3 = localDate.minusYears(3L).plusYears(1);;
System.out.println("localDate3 = " + localDate3);//localDate3 = 2023-10-19
}
2)java.time.Period、Duration
//Period.between 计算两个日期之间的差值
LocalDate local1 = LocalDate.of(2018, 12, 11);
LocalDate local2 = LocalDate.of(2020, 11, 11);
Period period = Period.between(local1, local2); //period = P1Y11M
System.out.println("period = " + period);
System.out.println(period.getYears());//1年
System.out.println(period.getMonths());//又11个月
System.out.println(period.getDays());//零0天
System.out.println(period.toTotalMonths()); //共23个月
//Duration.between 计算两个时间之间的差值
LocalDateTime localDateTime1 = LocalDateTime.of(2018, 12, 11,1,2,3);
LocalDateTime localDateTime2 = LocalDateTime.of(2020, 11, 11,11,22,33);
Duration duration = Duration.between(localDateTime1, localDateTime2);
System.out.println("duration = " + duration);//duration = PT16834H20M30S
System.out.println(duration.toDays()); //共701天
System.out.println(duration.toHours()); //共16834小时
System.out.println(duration.toMinutes());//共1010060分
System.out.println(duration.toSeconds());//共60603630秒
System.out.println(duration.toMillis()); //共60603630000毫秒
3)java.time.format.DateTimeFormatter
public static void main(String[] args) throws ParseException {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
/*
String format(TemporalAccessor temporal)-> 将日期对象按照指定的规则转成String
*/
System.out.println(dtf.format(LocalDateTime.now()));
/*
TemporalAccessor parse(CharSequence text)-> 将符合规则的字符串转成日期对象
*/
TemporalAccessor temporalAccessor = dtf.parse("2018-01-02 03:04:05");
/* 将TemporalAccessor转成我们常见的LocalDateTime日期对象
注意:
TemporalAccessor接口,子接口有Temporal
Temporal接口的实现类:LocalDate LocalDateTime
*/
LocalDateTime localDateTime = LocalDateTime.from(temporalAccessor);
System.out.println("localDateTime = " + localDateTime);
}
7、系统相关
1)java.lang.System
- final修饰的工具类,private构造器,静态方法
- 常用方法
- public static native long currentTimeMillis():返回以毫秒为单位的当前时间
- public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) :复制数组,从源数组的指定索引开始,到目标数组的指定索引开始,复制length个元素
- public static void exit(int status): 终止当前正在运行的 Java 虚拟机
- static String getProperty(String key):获取某个系统属性
2)java.lang.Runtime
- 每个Java程序都有一个
Runtime类实例,使应用程序能够与其运行的环境相连接 - 常用方法
- public static Runtime getRuntime(): 返回与当前 Java程序相关的运行时对象
- public long totalMemory():返回 Java 虚拟机中的内存总量。此方法返回的值可能随时间的推移而变化,这取决于主机环境
- public long freeMemory():返回 Java 虚拟机中的空闲内存量
8、其他
1)java.lang.Arrays
- 工具类,私有构造方法,封装了对数组的各种操作
- 常用方法
-
static int binarySearch(int[] a, int key) :要求数组有序,在数组中查找key是否存在,如果存在返回第一次找到的下标,不存在返回负数
-
static int[] copyOf(int[] original, int newLength) :根据original原数组复制一个长度为newLength的新数组,并返回新数组
-
static int[] copyOfRange(int[] original, int from, int to) :复制original原数组的[from,to)构成新数组,并返回新数组
-
static void sort(int[] a) :将数组元素按照从小到大进行排序
-
static void sort(int[] a, int fromIndex, int toIndex) :将数组的[fromIndex, toIndex)部分按照升序排列
-
static String toString(int[] a) :把数组的元素拼接为一个字符串,形式为:
[元素1,元素2,元素3。。。]
-
2)java.util.Scanner
- 读取键盘录入的基本数据类型和String类型的数据
/*
nextInt() 输入整数int型的
next():录入字符串 -> 遇到空格或回车就结束录入了,如果录入的数据是"a b",回车后只接收到a
nextLine():录入字符串 -> 遇到回车就结束录入了
避免nextLine()和其他next方法混用
*/
三、包装类
-
包装类就是基本类型对应的类
- byte->Byte;short->Short;long->Long;float->Float;double->Double;boolean->Boolean
- int->Integer;char->Character
-
基本数据类型和包装类之间的转换
-
装箱:将基本数据类型转为对应的包装类后,就可以使用包装类中的方法操作数据
- 通过包装类的静态方法
Integer.valueOf(123)
- 通过包装类的静态方法
-
拆箱:将包装类转为基本数据类型后,就可以做算数运算
- 通过包装类的实例方法
Integer对象.intValue()
- 通过包装类的实例方法
-
JDK5增加了自动装箱拆箱
Double d1 = 1.0; double d2 = 1.0; System.out.println(d1==d2);//true 和基本数据类型比较会自动拆箱,比较数据值 Integer i = 1000; double j = 1000; System.out.println(i==j);//true 会先将i自动拆箱为int,然后根据基本数据类型“自动类型转换”规则,转为double比较
-
-
基本数据类型和字符串之间的转换
- 基本数据类型-》字符串
- (常用)通过 + 拼接,如
String str = 123 +""; - 通过String类的静态方法
String.valueOf(123) - 通过包装类的静态方法
Integer.toString(123)
- (常用)通过 + 拼接,如
- 字符串-》基本数据类型
- (常用) 通过包装类(除了Character)的静态方法,如
Integer.parseInt("123") - 先把字符串转为包装类,然后可以自动拆箱为基本数据类型,如
Integer.valueOf("123") - 注意:如果字符串参数的内容无法正确转换为对应的基本类型,则会抛出
java.lang.NumberFormatException异常
- (常用) 通过包装类(除了Character)的静态方法,如
- 基本数据类型-》字符串
1256

被折叠的 条评论
为什么被折叠?



