异常和常用类和枚举
包装类
基本数据类型与包装类型
定义:专门将简单数据类型的数据进行封装,形成的对应的类.
装箱拆箱
手动装箱
概念:由基本数据类型, 完成向对应的包装类型进行转换。
作用:
为了更好的存储
方式1: 可以通过每一个包装类的构造方法来完成。 在每一个包装类的构造方法中,都有一
个与之对应的基本数据类型作为参数的重载方法。 此时, 直接将需要包装起来的基本数据类型, 写到构造方法的参数中即可完成装箱。
Byte n1 = new Byte((byte)1);
Short n2 = new Short((short)2);
Integer n3 = new Integer(3);
Long n4 = new Long(4L);
Float n5 = new Float(3.14f);
Double n6 = new Double(3.14);
Character n7 = new Character('a');
Boolean n8 = new Boolean(false);
【推荐使用】方式2: 可以通过包装类的静态方法 valueOf() 完成装箱。 每一个包装类中,都有一个静态方法 valueOf , 这个方法的参数是包装类型对应的基本数据类型的参数。 直接将需要包装起来的基本数据类型的数据, 写到这个方法的参数中, 即可完成对这个基本数据类型数据的装箱。
Byte n1 = Byte.valueOf((byte)1);
Short n2 = Short.valueOf((short)2);
Integer n3 = Integer.valueOf(3);
Long n4 = Long.valueOf(4);
Float n5 = Float.valueOf(3.14f);
Double n6 = Double.valueOf(3.14);
Character n7 = Character.valueOf('a');
Boolean n8 = Boolean.valueOf(true);
手动拆箱
概念: 由包装类型, 完成向对应的基本数据类型进行转换。
作用: 为了方便进行运算
方式: 使用每一个包装类对象的 xxxValue 可以实现。 这里的 xxx 就是需要转型的基本数据类型。 例如, 如果需要转型为int类型, 则直接调用 intValue 即可
Byte i1 = Byte.valueOf((byte) 100);
byte n1 = i1.byteValue();
Short i2 = Short.valueOf((short) 100);
short n2 = i2.shortValue();
备注: 某些包装类对象, 除了可以拆箱成对应的基本数据类型的数据之外。 还可以将包装起来的数字转成其他的基本数据类型的数据。 例如, Integer,除了有 intValue 之外, 还有byteValue 等方法。 其实, 就是将包装类中包装起来的int数据, 强转成byte类型返回结果。 在使用的时候, 找自己需要的方法去转型即可。
自动装箱拆箱
概念: 所谓的自动装箱和自动拆箱, 指的是在进行装箱和拆箱的时候, 不用再使用上面的方法完成装箱和拆箱的操作。 在JDK1.5之后, 装箱和拆箱是可以动完成的! 只需要一个赋值语句即可!
方式: 没有什么特殊语法, 直接去进行赋值即可。
注意: 既然已经有了自动的装箱和拆箱, 为什么还要掌握手动的装箱和拆箱。 因为, 在有些情况下, 自动的装箱和拆箱是不能使用的。
示例: 如果在一个类的重载方法中, 有两个方法的参数类型, 一个是基本数据类型, 一个是对应的包装类型。 此时, 将无法使用自动装箱和拆箱。 必须通过手动的装箱和拆箱完成对应的方法的调用。
享元原则
概念: 是程序设计的一个基本原则。 当我们需要在程序中频繁的用到一些元数据的时候, 此时, 我们可以提前将这些元数据准备好, 当需要的时候, 直接拿过来使用即可。 使用完成之后, 也不进行销毁, 以便下次继续使用。
包装类中的享元: 将常用到的基本数据类型对应的包装类对象,预先存储起来。 当使用到这些基本数据类型对应的包装类对象的时候, 可以直接拿过来用, 不用再实例化新的对象了。
示例: Integer类中, 将 [-128, 127] 范围内的数字对应的包装类对象预存到了一个Integer.cache 数组中, 每当我们用到这个范围内的数字的时候, 可以直接从这个数组中获取到元素。 如果用到了不在这个范围内的数字, 再去进行新的包装类对象的实例化。 这样,不用频繁的开辟空间、销毁空间, 节省了CPU资源。
字符串与基本数据类型转换
基本数据类型转型字符串类型
概念: 基本数据类型, 转成字符串, 希望得到的结果是这个数值转成字符串的样式。 其实, 就是直接给这个数值添加上双引号。
方式1: 可以利用字符串拼接运算符完成。 当加号两端有任意一方是字符串的时候, 此时都会自动的把另一方也转成字符串, 完成字符串的拼接。 所以, 当需要把一个基本数据类型的数据转成字符串的时候, 只需要在另一端拼接上一个空的字符串即可。
【推荐使用】方式2: 使用字符串的静态方法 valueOf 完成。
方式3: 借助包装类的实例方法 toString 方法。
方式4: 借助包装类的静态方法 toString 方法。
字符串类型转型基本数据类型
概念: 字符串类型转基本数据类型, 其实就是解析出这个字符串中的内容,转型成对应的基
本数据类型的表示。
注意事项1: 基本数据类型转字符串肯定是没问题的, 但是由字符串类型转到基本数据类型的时候, 可能会出现问题。字符串中的内容, 不一定能够转成希望转换的基本数据类型。 如果转换失败, 会出现 NumberFormatException 异常。
注意事项2: 对于整数来说,字符串中如果出现了其他的非数字的字符, 都会导致转整数失败, 即便是小数点, 也不可以转。 这里并没有转成浮点数字, 再转整数的过程。
方式1: 使用包装类的静态方法 valueOf 方法
方式2: 使用包装类的静态方法 parseXXX 方法。 这里的XXX就是要转换的基本数据类型
备注: 以上两种方式,都可以完成字符串类型到基本数据类型之间的转换。 如果希望直接转成基本数据类型, 推荐使用方式2; 如果希望转成包装类型, 推荐使用方式1。
关于字符类型的特殊说明:
字符串类型, 没有类似于上面的方式, 可以直接转成字符类型。 如果一个字符串, 要转成字符, 需要使用字符串的一个实例方法 charAt() 方法。 使用这个方法, 获取字符串中的指定下标位的字符。
实现进制间的转换
把十进制转成其它进制
Integer.toHexString() 转十六进制
I nteger.toOctalString() 转八进制
Integer.toBinaryString() 转二进制
常用类
常用类Math
概念
是一个数学类, 这个类中封装了很多用来做数学计算的方法。 当我们需要使用到数学计算的时候, 要能够想到这个类。 这个类中有很多封装好的数学公式, 而且, 都是静态方法, 方便调用。
常用静态常量
常用方法
常用类Random
概念
是一个专门负责产生随机数的类。 在Java中, Random类在 java.util 包中。 在使用之前,需要先导包。
其实, 随机数的产生, 是有一个固定的随机数算法的。 代入一个随机数种子, 能够生成一个随机数列。 但是由于算法是固定的, 因此会有一个“BUG”: 如果随机数的种子相同, 则生成的随机数列也完全相同。
常用方法
常用类BigInteger、BigDecimal
概念
这两个类,都是用来表示数字的类。 BigInteger表示整型数字, BigDecimal表示浮点型数字。 这两个类, 可以用来描述非常、非常、非常大的数字。 例如整数, long是最大的表示范围, 但是即便是long型, 也有它表示不了的情况。 BigInteger就是可以表示任意大小的数字。
BigInteger: 表示整型数字, 不限范围。
BigDecimal: 表示浮点型数字,不限范围, 不限小数点后面的位数。
常用方法
常用类Date
概念
是一个用来描述时间、日期的类。 在 java.util 包中!!!
注意点
比较Date和Data类
Date:日期类
Data:数据类,装的是二进制的数据
比较java.util.date和java.sql.date包
java.util.date 对应的是java的日期类型,包括年月日 时分秒
java.sql.date 对应的是数据库的日期类型 ,只包括 年月日
如果需要数据类型转换,从java.sql.date转成java.util.date是自动类型转换,反之是强制类型转换
常用方法
常用类SimpleDateFormat
概念
是一个用来格式化时间的类。 使用这个类, 一般有两种操作:
将一个 Date 对象, 转成指定格式的时间字符串。
将一个指定格式的时间字符串, 转成 Date 对象。
常用时间格式
在时间格式中, 有几个常见的时间占位符。
常用方法
parse 方法
会抛出一个编译时的异常。 在使用的时候, 目前, 直接使用一键修复(alt + Enter), 用try-catch 包围即可。
将一个字符串, 按照指定的格式进行解析。 如果字符串中的时间格式, 和对象实例化的时候给定的格式不同, 此时会出现异常。
常用类Calendar
概念
是一个用来描述时间、日期的类。 比Date的功能更加完善。 在Date类中, 有很方法都已经
被废弃了。 用Caleendar类中的某些方法来替代。
常用方法
System
概念
System 类包含一些有用的类字段和方法。它不能被实例化。
在 System 类提供的设施中,有标准输入、标准输出和错误输出流;对外部定义的属性和环境变量的访问;加载文件和库的方法;还有快速复制数组的一部分的实用方法。
常用字段
常用方法
Runtime
概念
运行时类,每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。应用程序不能创建自己的Runtime 类实例。
枚举
枚举的基本定义和使用
枚举的定义
定义枚举类型, 需要使用到关键字 enum 。 枚举的名字是一个标识符, 遵循大驼峰命名法。
枚举的使用
枚举是一种自定义的数据类型, 可以声明变量。 在使用的时候, 直接使用枚举类型.枚举值这样的形式进行枚举值的获取。
枚举中的成员定义
枚举的分析
枚举,其实可以认为是Object类的一个最终子类。 不能被其他的类、枚举继承。
枚举中的属性定义
public enum Gender {
Male, Female;
// 1. 在枚举中定义属性、方法、构造方法... 是需要写在枚举元素的下方!
// 如果需要在枚举中定义成员,需要在最后一个枚举元素后面添加一个分号。
public String desc;
}
异常
异常的结构和分类
异常的结构
在Java中,用 Throwable 类来描述所有的不正常的情况。 Throwable 有两个子类:Exception 和 Error 。
Error: 描述发生在JVM虚拟机级别的错误信息, 这些错误无法被处理, 不做为现在的重点。StackOverflowError: 栈溢出错误。
Exception: 描述程序遇到的异常。 异常是可以被捕获处理的, 是现在考虑的重点内容。
未经处理的异常,会导致程序无法进行编译或者运行。 因此在异常部分, 重点内容是:
异常该如何捕获处理。
Java中的异常的继承体系:
根类: Throwable
错误: Error
异常: Exception
运行时异常: RuntimeException
异常的分类
根据异常发生的位置
第一:普通的异常,会导致程序无法完成编译。 这样的异常被称为 – 编译时异常。 (Non-Runtime Exception: 非运行时异常, 但是由于异常是发生在编译时期的,因此,常常称为编译时异常。)
第二:Exception有一个子类-RuntimeException类, 在这个类中, 对异常进行了自动的处理。 这种异常不会影响程序的编译, 但是在运行中如果遇到了这种异常, 会导致程序执行的强制停止。 这样的异常被称为 – 运行时异常。
根据创建异常类的主体
第一:系统异常,系统提前定义好的,我们直接使用
第二:自定义异常,需要我们自己定义.
异常的工作原理
原理说明
1.在异常最初发生的位置创建一个异常的对象(new ArithmeticException()) 因为这里没有处理异常的能力,所以会将异常往上抛,抛给他所在的方法
2.div()方法也没有处理异常的能力,所以会继续往上抛,抛给调用这个方法的位置
3.调用div()方法的位置也没有处理异常的能力,所以会继续往上抛,抛给他所在的方法
4.main方法也没有处理异常的能力,所以会继续往上抛,抛给JVM,JVM会调用异常对象的打印方法,将异常信息打印到控制台
异常的特点
程序出现异常的时候,会打印异常的信息并中断程序,所以当有多个异常同时出现的时候,默认只能执行第一个.
异常的捕获处理
try-catch
如果一个异常不去处理, 会导致程序无法编译或者运行。
语法
try {
// 将可能出现异常的代码写到这里
// 如果这里的代码出现了异常, 从出现异常的位置开始, 到try代码段结束, 所有的
代码不执行。
}
catch (异常类型 标识符) {//捕获异常
// 如果try中的代码出现了异常,并且异常的类型和catch的异常的类型是可以匹配上的,就会执行这里的逻辑
}
catch会对try里面的代码进行监听,如果try里面的代码没有发生异常,catch不会执行,会直接执行后面的代码.如果try里面的代码发生了异常,catch会立刻捕获(效果:try里面的代码会立刻中断,直接执行catch)
注意事项
catch中捕获的异常类型, 一定要和try中实际出现的异常类型一致。 否则将捕获不到异常,会导致try中实际出现的异常没有被捕获处理, 依然可以终止程序的编译或运行。
多个catch子句
使用场景
如果在try代码段中, 出现了多种类型的异常, 此时如果需要对这些异常进行不同的处理,可以写多个catch子句。
在实际使用中:
如果要针对不同的异常,进行不同的处理,可以用多个catch。
如果要针对每一种异常,进行的处理方式相同,直接catch父类异常即可。
语法
try{
可能发生异常的代码
}catch(异常一 e){ //捕获异常 e就是要捕获的异常
对当前异常的处理
}catch(异常二 e){ //捕获异常 e就是要捕获的异常
对当前异常的处理
}catch(Exception e){ //捕获异常 e就是要捕获的异常
对当前异常的处理
}
**特点:**结构清晰,易于编写代码,
多个catch书写的先后顺序, 对异常捕获有影响吗?
- 如果多个catch捕获的异常类型之间, 没有继承关系存在, 此时先后顺序无所谓。
- 如果多个catch捕获的异常类型之间, 存在继承关系, 则必须保证父类异常在后, 子类异
常在前
一个catch捕获多种异常
使用场景
如果try中出现了多种异常,并且某些类型的异常,处理方式相同。 并且与其他类型的处理方式不同。 此时, 可以使用一个catch捕获处理多种异常。区分一个catch里面的多个异常时通过instanceof.
**缺点:**这种分类方式代码很混乱,所以不推荐.
注意事项
在一个catch子句中捕获的多种类型的异常中,不允许出现有继承关系的异常类型.
finally子句
概念
finally出现在try-catch子句的结尾, finally代码段中的内容, 始终会执行。
语法
try{
可能发生异常的代码
}catch(Exception e){ //捕获异常 e就是要捕获的异常
对当前异常的处理
}finally{
必须执行的代码:主要用于资源的释放:比如关闭数据库,关闭流,关闭锁等
}
特点
无论try代码段中有没有异常出现,无论try里面出现的异常没有被捕获处理,finally中的代码始终会执行。基于这个特点,常常在finally中进行资源释放、流的关闭等操作
作用范围
我们发现在catch中执行return后main方法结束,finally还能正常执行
catch中执行System.exit(0)后,程序退出,finally不能执行了
结论:只要当前的程序在运行,finally代码就能执行.
try-finally语句
try{
获取资源
}finally{
释放资源
}
特点
这个结构跟异常没有关系,主要用于资源的管理.
两个关键字
throw
一个异常对象,被实例化完成后,没有任何意义。不会影响到程序的编译或者运行。如果希望某一个异常对象生效(可以影响程序的编译、运行),需要使用关键字 throw 进行异常的抛出。
throws
用在方法的声明部分,写在参数列表后面,方法体前面。
定义在方法中,表示这个方法过程结束中,可能会遇到什么异常。
定义了throws异常抛出类型的方法,在当前的方法中,可以不处理这个异常,由调用方处理。
自定义异常
为什么要自定义异常
使用异常, 是为了处理一些重大的逻辑BUG。 这些逻辑BUG可能会导致程序的崩溃。 此时, 可以使用异常机制, 强迫修改这个BUG。
系统中, 提供很多很多的异常类型。 但是, 异常类型提供的再多, 也无法满足我们所有的需求。 当我们需要的异常类型, 系统没有提供的时候, 此时我们就需要自定义异常了。
如何自定义异常
其实,系统提供的每一种异常,都是一个类。所以,自定义异常,其实就是写一个自定义的异常类。
如果要自定义一个编译时的异常,需要继承自 Exception 类。
**特点:**对异常进行处理的所有工作都要我们手动完成
如果要自定义一个运行时的异常,需要继承自RuntimeException 类。
特点:所有的工作我们都可以不管
在重写方法中使用异常
注意点:
子类的同名方法中声明的异常等级要<=父类的.
如果子类同名方法声明了异常,父类必须声明异常.
父类抛出了异常,子类在重写方法的时候,可以不抛出异常
如果父类方法抛出的异常是 编译时异常
子类重写方法的时候,可以抛出相同的异常,或子类异常
子类重写方法的时候,可以抛出运行时异常
如果父类方法抛出的异常是 运行时异常
此时我们就需要自定义异常了。
如何自定义异常
其实,系统提供的每一种异常,都是一个类。所以,自定义异常,其实就是写一个自定义的异常类。
如果要自定义一个编译时的异常,需要继承自 Exception 类。
**特点:**对异常进行处理的所有工作都要我们手动完成
如果要自定义一个运行时的异常,需要继承自RuntimeException 类。
特点:所有的工作我们都可以不管
在重写方法中使用异常
注意点:
子类的同名方法中声明的异常等级要<=父类的.
如果子类同名方法声明了异常,父类必须声明异常.
父类抛出了异常,子类在重写方法的时候,可以不抛出异常
如果父类方法抛出的异常是 编译时异常
子类重写方法的时候,可以抛出相同的异常,或子类异常
子类重写方法的时候,可以抛出运行时异常
如果父类方法抛出的异常是 运行时异常
子类在重写的时候,可以是任意的运行时异常,不能是编译时异常