概述
异常
异常的概念以及分类
-
指的是程序在执行的过程中,出现的非正常的情况,最终会导致JVM的非正常停止
-
异常的根类是
java.lang.Throwable
,它下面有两个子类.java.lang.Exception
以及java.lang.Error
,其中Exception下有一个子类是RuntimeException -
Error:工程师不能处理,只能尽量避免,是不可预知的.Error代表错误.相当于程序得了一个无法治愈的毛病,必须修改源代码,程序才能继续运行
-
Exception:由于使用不当导致,可以避免,是编译时期的异常,进行编译(写代码)java程序出现的问题,RuntimeException:运行时期异常,java程序运行过程中出现的问题,相当于程序出现了一个小毛病,把异常处理掉,程序才能继续执行
异常的处理
-
throw关键字(如果不抛出异常,jvm也会自动帮我们抛出异常,使我们的异常更容易被理解)
-
作用:可以使用throw关键字在指定的方法中抛出指定的异常
-
使用格式:throw new XXXException("异常产生的原因")
-
注意:
-
throw关键字必须写在方法的内部
-
throw关键字后边new的对象此项是Exception或者其子类对象
-
throw关键字抛出指定的异常对象,我们就必须处理这个异常
-
throw关键字后边创建的是RuntimeException或者是RuntimeException的子类对象,我们可以不处理,默认交给JVM处理(打印异常对象,中断程序)
如果是编译时期异常,我们就必须处理这个异常,要么trycatch,要么throws.
-
-
-
程序的健壮性判断: 可以借助Object的工具类:Objects
-
public static <T> T requireNonNull(T obj) { if (obj == null) throw new NullPointerException(); return obj; }
-
这个还有一个重载,参数为(T obj , String message)
-
异常处理的两种方式
throws关键字
-
throws关键字:异常处理的第一种方式,交给别人处理
-
throws 基本都是编译时期的异常时(又不想使用try)
-
作用:
-
当方法内部抛出异常对象的时候,那么我们就必须处理这个异常对象
-
可以适应throws关键字处理异常对象,会把异常对象声明抛出给方法的调用者处理(自己不处理,给别人处理),最终交给jvm处理-->中断处理
-
-
使用格式:在方法声明的同时使用
-
注意:
-
throws关键字必须写在方法声明处
-
throws关键字后边声明的异常必须是Exception或者是其子类
-
方法内部如果抛出了多个异常对象,那么throws后边也必须声明多个异常对象,如果抛出的多个异常对象有子父类关系,那么直接声明父类异常即可
-
调用了一个声明抛出异常的方法,我们就必须处理声明的异常,要么继续使用throws声明抛出,交给方法的调用者处理,最终交给jvm,要么try...catch自己处理异常
-
-
最简单的使用: throws Exception(因为异常继承自Exception)
try...catch
-
异常处理的第二种方式,自己处理异常
-
格式:
try{
可能产生异常的代码
}catch(){
异常的处理逻辑,怎么处理异常对象
一般在工作中,会把异常的信息记录到一个日志中
}
-
注意:
-
try中可能会抛出多个异常对象,那么就可以使用多个catch来处理这些异常对象
-
如果try中产生了异常,那么就会执行catch中的异常处理逻辑,执行完毕catch中的处理逻辑,继续执行try...catch之后的代码
-
如果try中没有产生异常,那么就不会执行catch中的异常处理逻辑,执行完try中的代码,继续执行try...catch之后的代码
-
try...catch是捕获不了错误的.
-
Throwable类的几个方法
-
String getMessage():返回此throwable的简短描述
-
String toString():返回此throwable的详细描述字符串
-
void printStackTrace:jvm打印异常,默认此方法,打印的是最全面的
finally代码块
-
finally代码块是与try一起使用的
try{
可能产生异常的代码
}catch(){
异常的处理逻辑,怎么处理异常对象
一般在工作中,会把异常的信息记录到一个日志中
}finally{
无论是否出现异常都会执行
}
-
注意:
-
finally不能单独使用,必须和try一起使用
-
finally一般用于资源释放(资源回收),无论程序是否出现异常,最后都要释放(IO流)
-
异常注意事项
-
多个异常的捕获处理
-
多个异常分别处理
-
多个异常一次捕获.多次处理
一个try多个catch的注意事项
-
catch里面的异常变量,如果有子父类关系,那么子类的异常变量必须下载上边,否则会报错
-
-
多个异常一次捕获,一次处理
-
-
注意:运行时候的异常.可以不处理,即不捕获也不声明抛出,默认给jvm处理
-
如果finally里面有return语句,则永远返回finally中的结果,避免该情况
-
子父类的异常
-
如果父类抛出了多个异常,子类重写父类方法的时候,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常
-
父类方法中没有抛出异常,子类重写该方法时候也不可以抛出异常.此时子类产生的异常,只能捕获处理,不能声明抛出.
-
注意:父类异常时什么样子,子类异常就什么样子
-
自定义异常
-
java给我们提供的异常类不够的时候,我们自定义一个异常类.
-
格式:
public class XXXException extends Exception|RuntimeException{
添加一个空参数的构造方法
添加一个带异常信息的构造方法
}
-
注意:
-
自定义异常类一般都是以Exception结尾,说明该类是一个异常类
-
自定义异常类,必须继承Exception或者RuntimeException
如果继承Exception,那么自定义的异常类就是一个编译时期异常,如果方法内部抛出了编译时期异常,就必须处理这个异常,要么throws要么try...catch
如果继承RuntimeException,就是运行时期的异常,我们无需处理,交给jvm处理(终端处理)
-
自定义异常类练习
在一款角色扮演游戏中,每一个人都会有名字和生命值;角色的生命值不能为负数
要求:当一个人物的生命值为负数negative的时候需要抛出自定的异常
person类
package com.qin.test.Test10;
public class Person {
private String name;
private int lifeValue;
public Person() {
}
public Person(String name, int lifeValue) throws LifeValueNegativeException {
this.name = name;
if (lifeValue < 0) {
throw new LifeValueNegativeException("生命值为负异常.");
} else {
this.lifeValue = lifeValue;
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLifeValue() {
return lifeValue;
}
public void setLifeValue(int lifeValue) throws LifeValueNegativeException {
if (lifeValue < 0) {
throw new LifeValueNegativeException("生命值为负异常.");
} else {
this.lifeValue = lifeValue;
}
}
}
自定义异常类
package com.qin.test.Test10;
public class LifeValueNegativeException extends Exception {
public LifeValueNegativeException() {
}
public LifeValueNegativeException(String message) {
super(message);
}
}
Test类
package com.qin.test.Test10;
public class PersonTest {
public static void main(String[] args) {
try {
Person person = new Person("jack",-1000);
} catch (LifeValueNegativeException e) {
e.printStackTrace();
}
}
}
//com.qin.test.Test10.LifeValueNegativeException: 生命值为负异常.
//at com.qin.test.Test10.Person.<init>(Person.java:13)
//at com.qin.test.Test10.PersonTest.main(PersonTest.java:6)
多线程
-
并发:指两个或多个事件在同一个时间段内发生
-
相当于一个人吃两个馒头
-
-
并行:指两个或多个事件在同一时刻发生(同时发生)
-
相当于两个人吃两个馒头
-
-
进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。
-
线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
-
java采用的是抢占式调度
-
主线程:(执行main方法的线程.)程序入口所在的线程就是主线程.
-
单线程程序:java程序只有一个线程
-
使用线程名.run()也会调用,但是没有调用线程
多线程练习题
创建三个子线程,在每个线程中开启10万次的循环,线程1循环中将循环自增变量i赋值给Integer类型变量 a,线程2循环中将字符串"黑马程序员"赋值给String类型变量b,线程3循环中将字符串"黑马程序员"和循环自增变量i拼接后赋值给String类型变量c
分别计算三个线程完成任务所用的毫秒值
main方法
public class Test11 {
public static void main(String[] args) {
MyThread1 m1 = new MyThread1();
MyThread2 m2 = new MyThread2();
MyThread3 m3 = new MyThread3();
m1.start();
m2.start();
m3.start();
}
}
1,2,3子线程类
package com.qin.test.Test11;
public class MyThread1 extends Thread {
@Override
public void run() {
long start = System.currentTimeMillis();
Integer a = 0;
for (int i = 0; i < 100000; i++) {
a = i;
}
long end = System.currentTimeMillis();
long time = end - start;
System.out.println("线程1:"+time);
}
}
package com.qin.test.Test11;
public class MyThread2 extends Thread {
@Override
public void run() {
long start = System.currentTimeMillis();
String b = "";
for (int i = 0; i < 100000; i++) {
b = "黑马程序员";
}
long end = System.currentTimeMillis();
long time = end - start;
System.out.println("线程2:"+time);
}
}
package com.qin.test.Test11;
public class MyThread3 extends Thread {
@Override
public void run() {
long start = System.currentTimeMillis();
String c = "";
for (int i = 0; i < 100000; i++) {
c = "黑马程序员"+i;
}
long end = System.currentTimeMillis();
long time = end - start;
System.out.println("线程3:"+time);
}
}
// 结果
//
//线程1:4
//线程2:1
//线程3:54
最后
以上就是威武项链为你收集整理的异常,多线程的创建的全部内容,希望文章能够帮你解决异常,多线程的创建所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复