目录
异常:
异常:程序没有按照预计的结果运行,在运行的过程中发生了"错误"
异常的基本语法:
try{
//可能产生异常的代码,算术异常,数组越界,空指针
}catch(异常类型){
//出现异常后如何处理
}finally{
//无论如何都会执行的代码
}
1.使用try...catch...处理异常
一旦try中的代码出现异常,那么就不会继续往下执行,而是交给catch中的代码执行,catch执行完毕继续往下执行
public static void main(String[] args) {
int[] data = {1,2,3};
System.out.println("before...");
try {
System.out.println(data[100]);
System.out.println("try中的代码");
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("异常产生了");
}
System.out.println("after...");
}
before...
异常产生了
after...
2.异常也是类catch只能铺货相应的类型
Exception是所有异常的父类
catch块中捕获的是exception这个类型,就可以接收所有的异常类型(不推荐)
若知道可能产生的异常类型(数组越界,空指针)catch捕获明确的类型
若不清楚异常类型就是用exception,所有的异常子类都会向上转型为exception引用
3. finally代码块:无论如何都会执行
资源的释放,方法的关闭,关闭数据库的连接,关闭文件操作都在finally代码块中,保证资源会正确释放
不要在finally代码快中写返回值!!!
public static int test(){
try{
int[] data = {1,2,3};
data[100] = 10;
return 10;
}catch (ArrayIndexOutOfBoundsException e){
e.printStackTrace();
return 20;
}finally {
System.out.println("finally代码块");
return 30;
}
}
结果:
java.lang.ArrayIndexOutOfBoundsException: 100
at www.bit.se.Try.TryTest.test(TryTest.java:9)
at www.bit.se.Try.TryTest.main(TryTest.java:33)
finally代码块
30
3.异常的处理流程
1. 程序会先执行try中的代码
2.如果try中的代码出现异常,就会结束try中的代码,看和catch中的异常类型是否匹配
3.如果找到匹配的代码就会执行catch中的代码
4.如果没有找到匹配的异常类型就会将异常向上传递到上层调用者
5.无论是否找到异常匹配类型,finally代码都会执行
6.如果上层调用者也没有处理异常,就继续向上传递
7.一直到主方法,也没有处理异常就会交给JVM来进行处理,这时程序就会异常终止
4.throw和throws:人为抛出异常
throws:用在方法的声明上,表示该方法可能会产生异常,但是本方法不处理,将异常抛给调用者
public static void fun()throws ArrayIndexOutOfBoundsException{
int[] arr = {1,2,3};
System.out.println(arr[100]);
}
throw:用在方法内部,表示人为产生异常对象并抛出
异常对象的产生是发生异常后由JVM产生的,若需要人为产生,就要使用throw关键字!!!
public static void fun(){
int[] arr = {1,2,3};
throw new NullPointerException("抛出一个异常");
}
5.异常体系:JDK内部异常继承关系
Java中的异常分为两大类,一类是"受查异常",另一类是"非受查异常"
非受查异常:
RuntimeException及其子类,包括Error称之为"非受查异常",编译阶段可以不显示异常处理(try...catch/throws抛出) 下图中蓝色部分
RuntimeException(运行异常,编译阶段不报错,运行时出错,数组越界异常/空指针异常/类型转换异常)
Error - 程序内部错误,出现这个错误,程序没法正常执行下去,只能推出程序
堆内存溢出错误/栈溢出错误
受查异常:
下图红色为受查异常,必须在编译阶段进行异常处理,否则就会编译出错
a.使用try...catch处理
b.throws向上抛出
6.自定义异常
JDK内部已经帮我们定义好了很多异常类,但在某些业务场景下,出现的错误需要我们自定义异常类(用户登录,用户名不对,密码不对,这种错误需要我们自定义异常)
自定义异常需要继承相关的两个父类
若希望这个异常必须显示处理-继承Exception父类
若这个异常不需要显示处理-RuntimeException
public class RuntimeExceptionText {
private static final String USER_NAME = "zs";
private static final String PASSWORD = "123";
public static void main(String[] args) {
System.out.println("请输入用户名:");
Scanner sc = new Scanner(System.in);
String userName = sc.nextLine();
System.out.println("请输入密码");
String passWord = sc.nextLine();
if(!USER_NAME.equals(userName)){
throw new UserNameException("用户名错误");
}
if(!PASSWORD.equals(passWord)){
throw new PasswordException("密码错误");
}
}
}
class UserNameException extends RuntimeException{
public UserNameException(String msg) {
super(msg);
}
}
class PasswordException extends RuntimeException{
public PasswordException(String msg) {
super(msg);
}
}
包装类:
就是把8大基本类型封装到类中
a.Object类可以接收所有引用数据类型(数组,类,接口),为了让Object类可以接收Java中一切内容,引入包装类,就是把基本类型封装到类的对象之中就产生了包装类
b.包装类的默认值是null
包装类类型:
整形:(Byte,Shot,Integer,Long);
浮点型:(Float,Double);
char类型包装类:Character
boolean类型的包装类:Boolean
装箱:将基本类型的数组保存到包装类对象中
int val = 10;
Integer i1 = new Integer(val);
拆箱:将包装类对象中的数值还原为基本类型
int ret = i1.Value();
自动拆装箱:使用包装类就和基本类型一样
public static void main(String[] args) {
//自动装箱
Integer i2 = 10;
//自动拆箱
i2 += 20;
System.out.println(i2);
}
a.默认值不同,包装类的默认值都是null,基本类型的默认值就是其基本类型的默认值
b.比较相等,仍然使用equals方法比较,所有类对象的比较都使用equas方法!!!
同字符串常量池
当使用整形包装类的自动拆装箱时,JVM会缓冲相应的数值
Integer常量池,默认在-128-127之间,都会缓冲到常量池中
Integer i1 = 130;
Integer i2 = 130;
System.out.println(i1 == i2);//false
i1 = 120;
i2 = 120;
System.out.println(i1 == i2);//true
阿里编码规范:所有POJO(普通类)的所有成员变量一律使用包装类替代基本类型
泛型:
定义泛型对象时,只能使用类
基本类型不能保存到泛型中,必须使用包装类
当用户不小心输入的x和y是不同类型时,编译没问题,但取出x和y的值时,强制类型转换就会报错,运行时异常
一般来说,我们要求把所有的错误都提前暴露在编译阶段,程序还没跑起来就能发现错误!
泛型:相当于守门员,编译阶段检测类型是否一致的手段
泛型就是在类定义时不明确类型,在使用时明确类型
定义泛型使用"<>"操作符
<T>:称之为类型参数,可以使用任何字符,中文也可以,规范是单个的大写字母
T:表示任意类型
K:键值对,key值
V:value值
E:单个元素
public class MyPoint <T>{
//此时X的类型不确定,在产生这个对象时确定类型
private T x;
private T y;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
public static void main(String[] args) {
MyPoint<String> myPoint = new MyPoint<>();
//类型不一致报错
myPoint.setY(10);
myPoint.setX("北纬20度");
System.out.println(myPoint.getX());
}
}
若泛型类中存在多个类型参数,成员变量的类型不一定一致
产生对象时,T和E的类型可以相同也可以不同
public class MypointNew <T,E>{
private T x;
private E y;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public E getY() {
return y;
}
public void setY(E y) {
this.y = y;
}
public static void main(String[] args) {
MypointNew<String,Integer> mypointNew = new MypointNew<>();
mypointNew.setX("hello");
mypointNew.setY(10);
}
}
集合框架初识:所谓的集合,就是用来保存和操作数据的一些类
List:线性表的父接口
常用子类:
ArrayList(底层是一个动态数组实现的线性表)
LinkedList(底层是一个双向链表实现的线性表)
public class ListTest {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
List<String> list1 = new LinkedList<>();
list.add("1");
list.add("2");
list.add("2");
list.add("3");
list.add(1,"6");//16223
list.remove(1);//1223
list.remove("2");//123
System.out.println(list.get(1));//2
System.out.println(list.set(1,"6"));//2
System.out.println(list.contains("3"));//true
System.out.println(list);//[1,6,3]
}
}
相当于二维数组
List<List<Integer>> list = new ArrayList<>();
List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(3);
list1.add(5);
List<Integer> list2 = new ArrayList<>();
list2.add(2);
list2.add(4);
list2.add(6);
list.add(list1);
list.add(list2);
System.out.println(list);//[[1, 3, 5], [2, 4, 6]]
public class MyPoint <T>{
//此时X的类型不确定,在产生这个对象时确定类型
private T x;
private T y;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
public static void main(String[] args) {
MyPoint<Integer> myPoint = new MyPoint<>();
myPoint.setY(10);
myPoint.setX(20);
System.out.println(myPoint.getX());
}
}
public class MypointNew <T,E>{
private T x;
private E y;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public E getY() {
return y;
}
public void setY(E y) {
this.y = y;
}
public static void main(String[] args) {
MypointNew<String,Integer> mypointNew = new MypointNew<>();
mypointNew.setX("hello");
mypointNew.setY(10);
}
}