0%

Java中异常

基本概念

在Java语言中,将程序执行中发生的不正常情况称为“异常”。

  • 执行过程中所发生的异常事件可分为两类

1.错误:Java虚拟机无法解决的严重问题,比如jvm系统内部错误,资源耗尽等情况。

2.异常:其他因编程错误或者偶然外在因素导致的一般性问题,可以使用针对性的代码进行处理。比如空指针的访问,访问不存在的文件等等。异常也可以分为两个大类:运行时的异常和编译时的异常。

异常体系图

对于不同的jdk版本异常体系图显示的会有所不同,但是Throwable是Error与Exception的父类。而我们所说的编译异常与运行异常,编译异常是在生成class文件时发现的,而运行异常则是在class文件运行时发生的。

image-20220704160152014

常见五个运行时的异常

  • NullPointException空指针异常,当程序试图在需要对象使用null时,抛出该异常。
1
2
3
4
5
6
7
8
9
package Learn;
public class Test {
public static void main(String[] args) {
String name =null;
System.out.println(name.length());

}
}

image-20220704160212340

AritmeticException数字运行异常

1
2
3
4
5
6
7
package Learn;
public class Test {
public static void main(String[] args) {
int a=10/0;
System.out.println(a);
}
}

image-20220704160240284

  • ArrayIndexOutOfBoundsException数组下标越界异常
1
2
3
4
5
6
7
package Learn;
public class Test {
public static void main(String[] args) {
int []a={1,2,3};
System.out.println(a[4]);
}
}

image-20220704160341244

  • ClassCastException类型转换异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package Learn;
public class Test {
public static void main(String[] args) {
A b=new B();
C c=(C) b;
}
}
class A{

}
class B extends A{

}
class C extends A{

}

image-20220704160405671 NumberFormatException数字格式不正确

1
2
3
4
5
6
7
package Learn;
public class Test {
public static void main(String[] args) {
String name="鲁迅";
int num=Integer.parseInt(name);
}
}

image-20220704160416946常见的编译异常

  • SQLException 操作数据库发生的异常
  • IOException 操作文件时发生的异常
  • FileNotFoundException 操作不存在文件时,发生的异常
  • ClassNotFoundException 加载类不存在时,发生异常

Java中异常处理的两种方式

try-catch-finally

  • 程序员在代码中国捕获发生的异常,自行处理

try{

可能发生异常的代码块}catch(Exception e){

系统将其封装成Exception对象 ,传递给catch。也可以在这里增加自己的业务逻辑

}finally{

不管是否有异常发生,finally代码块一定会执行

}

注意事项:

如果在try中发生异常了,则其后面的语句不会执行,直接进入catch中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package Learn;
public class Test {
public static void main(String[] args) {
String name="鲁迅";
try{
int num=Integer.parseInt(name);
System.out.println("我又没有输出");
}
catch (Exception e){
System.out.println("发生异常了");
}finally {
System.out.println("运行结束");
}
}
}

image-20220704161623702try{}finaly{}也可以直接使用,但是程序会崩溃。并且finaly中语句会执行,但是其后面的程序并不会执行。

throws处理机制

我们假设jvm虚拟机调用main方法,而main方法调用了f1方法,f1调用f2方法。如果f2方法有异常,那么在f2中可以用try-catch方法自己处理,也可以throws抛出给f1方法,同理f1也可以做出相同的操作,而方法如果一直往上抛出,最终给到了jvm虚拟机会直接打印出来异常信息,进而中断程序。

在Java中,如果我们没有用操作区管理异常,则默认会一直向上抛出,直到jvm,在下面中我们可以看到f1中存在的异常抛出给了main方法,main方法捕捉并且进行处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package Learn;
public class Test {
public static void main(String[] args) {
AA aa = new AA();
try {
aa.f1();
}catch (ArithmeticException arithmeticException){
System.out.println("有错误");
}

}
}
class AA{
public void f1() throws ArithmeticException {
int a=10/0;
}
}

image-20220704161713266细节问题

对于问题中的编译异常必须进行处理,而运行异常则有默认的处理机制

对于子类重写父类方法时,子类抛出的异常必须是父类异常的子类型或者相同

1
2
3
4
5
6
7
8
9
10
11
class AA{
public void f1() throws Exception {
int a=10/0;
}
}
class BB extends AA{
@Override
public void f1() throws ArithmeticException{

}
}

点击并拖拽以移动

Java中的自定义异常

当我们的程序中出现某种错误,但是我们的Exception并没有对其进行详细的描述,这时我们可以自定义异常,来显示信息。

  1. 我们自定义异常类去继承Exception类或者RuntimeException
  2. 如果继承Exception则属于编译异常
  3. 如果继承RuntimeException,则输入运行异常

下面的这中情况是自定义编译异常,必须在main方法中抛出或者处理异常。

但是我们默认情况下使用运行异常,这种情况下系统可以自己调用,而不用我们自己手写相关的代码情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package Learn;
public class Test {
public static void main(String[] args) throws Judge {
int age=152;
if (age<=10||age>=120){
throw new Judge("年龄错误");
}

}
}
class Judge extends Exception{
public Judge(String message) {
super(message);
}
}

image-20220704155853115

throws 异常处理的一种方式,用在方法声明处,后面是异常的类型
throw 手动生成异常对象的关键字,在方法体中,后面是异常的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package Learn;
public class Test {
public static void main(String[] args) throws Judge {
int age=152;
if (age<=10||age>=120){
throw new Judge("年龄错误");
}

}
}
class Judge extends Exception{
public Judge(String message) {
super(message);
}
}

image-20220704161819183

概念

JVM:英文名称为Java virtual machine,即Java虚拟机,是Java的核心机制,负责执行指令,管理数据、内存、寄存器等,包含在JDK之中。

JDK:英文名称为Java development kit,即Java开发工具包。JDK=JRE+Java开发工具

JRE:英文名称为Java runtime environment,即Java运行环境。JRE=JVM+Java的核心类库(类)

作用

JVM对于不同的平台(window平台,linux平台等),拥有不同的虚拟机,JVM虚拟机屏蔽了底层运行的差别,实现了’一次编译,到处运行‘。

对于Java中的编译与运行,举个例子:

这是一可以输出’你好‘个Java程序

其次在cmd中利用Javac语句运行test.java,可以发现生成了一个test.class的文件,这便是一个编译的过程

image-20220703174839336

而运行则是利用Java语句去运行该文件,注意还是test.java文件,只不过这一次是运行过程。(这里没有去设置编码字符集,输出乱码)

image-20220703174905018

JDK=JRE+Java开发工具(java,javac,javadoc,javap等Java运行所需要的编译运行等语句)小伙伴们仔细去查看自己jdk下面的bin文件,其中包含了许多Java的开发工具。

image-20220703174915751

**JRE=JVM+Java的核心类库(类)**,如果只想要运行一个开发好的Java程序,计算机中只需要安装JRE即可,如果你想要自己的程序在别的电脑上运行,就把JRE与自己的程序一起打包。

Java中常用的转义字符

\t 制表位,实现对齐的功能
\n 换行符,本义是光标往下一行
\(\\) 输出1个斜杠(输出两个斜杠)
" 输出一个双引号
\r **一个回车,此处回车与换行不同,**本义是光标重新回到本行开头
1
2
3
4
5
6
7
8
9
10
11
public class Test {
public static void main(String [] args){
System.out.println("北京上海天津");
System.out.println("北京\t上海\t天津");
System.out.println("北京\n上海\n天津");
System.out.println("北京\\上海\\天津");
System.out.println("北京\\\\上海\\\\天津");
System.out.println("北京\"上海\"天津");
}
}

image-20220703174446820

\r与\n之间的不同

首先我们单单运行这个语句输出,可以发现输出语句中仅仅指输出的一行”你好“,只是在本行实现了一些输出

1
2
3
4
5
6
public class Test {
public static void main(String [] args){
System.out.print("\r你好");
}
}

image-20220703174627134

说完了他们两个的区别,我们再来细说一下\r的运行,大家仔细观察一下这个语句的运行结果,可以发现他仅仅输出了”您好“,而没有输出”我是北京人“,这是在编译过程中idea的编译,回车之后,只会输出后面的字符

1
2
3
4
5
6
public class Test {
public static void main(String [] args){
System.out.print("我是北京人\r你好");
}
}

image-20220703174615737

这时候可能有的同学的输出可能会不一样了,下面是用窗口命令运行以下程序之后的结果,可能有的小伙伴奇怪,不应该输出99吗???不同的编译器编译出来效果也是不同的,大家有时间可以尝试一下其他系统下的效果。

1
2
3
4
5
6
public class Test {
public static void main(String [] args){
System.out.print("12345\r99");
}
}

image-20220703174549146

Java中的注解

三种注解

@Override

限定于某个某个方法,重写父类的方法,该注解只能用于方法

1
2
3
4
@Override
public String toString(){
return season+characteristic;
}

源码,下面的并非一个接口,而是一个注解类,是jdk1.5之后添加的

1
2
3
4
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

@Deprecated

用于表示某个方法已经过时,但是过时并不是表示不可以使用,这个注解可以做到新旧版本的过度。

1
2
3
4
@Deprecated
public void say(){

}

@SuppressWarning

抑制编译器警告

可以使用该注解,取消编译器对这个的警告,例如下面的方法中,就可以抑制所有的警告all,当然我们也可以精确的仅仅抑制某个警告,比如使用unused去抑制编译器对我们从没有使用的一个属性的警告。而我们使用的SuppressWarnings范围囊括这一个方法或者类,如果在main方法前使用,则我们可以抑制main方法的警告,而不妨碍别的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package Learn;
public class Test {
public static void main(String[] args) {
System.out.println(Season.SPRING.toString());
System.out.println(Season.SUMMER.toString());
System.out.println(Season.AUTUMN.toString());
System.out.println(Season.WINTER.toString());
System.out.println(Season.SPRING.name());
System.out.println(Season.SPRING.hashCode());
//输出相应的编号,编号从0开始
System.out.println(Season.SPRING.ordinal());
Season []values=Season.values();
for (Season A :values){
System.out.println(A);
}
System.out.println(Season.valueOf("SPRING"));
//System.out.println(Season.valueOf("dj"));
System.out.println(Season.SPRING.compareTo(Season.AUTUMN));

}
}
@SuppressWarnings("all")
enum Season{
SPRING("春天","温暖"),
SUMMER ("夏天","炎热"),
AUTUMN ("秋天","凉爽"),
WINTER ("冬天","寒冷"),
OTHER;
private String season, characteristic;
/**将构造其私有化,防止在main方法中直接new对象*/
private Season(){}
private Season(String season,String characteristic){
this.season=season;
this.characteristic=characteristic;
}


@Override
public String toString(){
return season+characteristic;
}
@Deprecated
public void say(){

}

}

四种元注解

  1. Retntion(保留)指定注解的作用范围,三种source,class,runtime
  2. Target 指定注解可以在那些地方使用
  3. Documented指定该注解是否会在Javadoc中体现在页面中
  4. Inherited 子类会继承父类注解

比如下面的类Target表示在方法中使用,而Retenttion表示在源文件中保留注释

1
2
3
4
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

Java标识符规则与规范

标识符的概念

Java对各种变量,方法和类型的命名使用的字符称为标识符,一般来说可以自己起名字的地方就叫标识符。

命名规则

  1. 由26英文字母与数字或者$组成。(使用其他都会报错)
  2. 不可以数字开头。int 3as=5;
  3. 不可以使用关键字和保留字,但是可以包含这字关键字与保留字。int sum=5;
  4. Java中区分大小写,长度无限制。big与Big标识的含义不一样
  5. 标识符不可以包含空格。int A B=3

命名规范

  • 包名:

多单词组成时所有字母都要小写。比如:com.sun.test

  • 类名,接口名:

多单词组成时,所有单词的首字母都要大写。比如:GoodSum

  • 变量名,方法名:

多单词组成时,第一个首字母小写,第二个开始每个单词首字母大写。比如:bigNum

  • 常量名:

所有字母都要大写。多个单词时用下划线进行链接。比如:THE_BIGGEST_NUM。

Collections工具类介绍

Collection工具类是一个提供了操作Set、List和Map等集合发工具类,Collection中提供了一系列惊天的方法对集合元素进行排序、查询、和修改等操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.*;

public class Test {
public static void main(String[] args) {
List list=new ArrayList();
list.add("asc");
list.add("ascgj");
list.add("sbs");
list.add("adbnde");
list.add("dnjj");
System.out.println(list);
//反转
Collections.reverse(list);
System.out.println(list);

//随机排序
Collections.shuffle(list);
System.out.println(list);
//自然排序
Collections.sort(list);
System.out.println(list);
//进行交换
Collections.swap(list,1,2);
System.out.println(list);
}
}

image-20220704181002073

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.util.*;

public class Test {
public static void main(String[] args) {
List list=new ArrayList();
list.add("asc");
list.add("ascgj");
list.add("sbs");
list.add("adbnde");
list.add("dnjj");
System.out.println(list);
//自然顺序的最大元素
System.out.println(Collections.max(list));
//某个值出现的次数
System.out.println(Collections.frequency(list,"asc"));
//拷贝复制
ArrayList arrayList=new ArrayList();
//如果不进行操作,会抛出异常,需要对其进行复制扩容
for (int i=0;i<list.size();i++){
arrayList.add("");
}

Collections.copy(arrayList,list);
System.out.println(arrayList);

//替换
Collections.replaceAll(list,"asc","唐末");
System.out.println(list);
}
}

image-20220704181011148

Collection常用方法

由于Collection是一个接口,无法进行实例化,我们可以通过继承了的子类ArrayList进行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package Learn;

import java.util.ArrayList;
import java.util.List;

public class Test {
public static void main(String[] args) {
List list=new ArrayList();
//添加的方法
list.add("jack");
list.add("10");
list.add(12);
System.out.println(list);
//remove删除指定元素,既可以是位置,也可以是指定的元素
//删除了0号位置的jack
list.remove(0);
System.out.println(list.remove("10"));
System.out.println(list);
//查找元素是否存在
System.out.println(list.contains(10));
System.out.println(list.contains(12));

//获取元素个数
System.out.println(list.size());
//判断是否为空
System.out.println(list.isEmpty());

//清空元素
list.clear();
System.out.println(list.size());
//添加多个元素,传入的为实现Collection接口的方法
List list2=new ArrayList();
list2.add(100);
list2.add(10);
list2.add("骄傲成");
list.addAll(list2);
System.out.println(list);
//查找多个元素是否存在,传入的还是Collection的对象
System.out.println(list.containsAll(list2));

//删除多个元素
System.out.println(list.removeAll(list2));


}
}


image-20220306162642857