Java学习13(异常)
Posted Zephyr丶J
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java学习13(异常)相关的知识,希望对你有一定的参考价值。
Java学习13
今天怎么过呢,还没想好哈哈
2021.5.8(下了雷阵雨马上就出彩虹了,哈哈,心情瞬间满格了),今天争取把这个复习完把
对日期的处理
java.util.Date
获取系统当前时间(精确到豪秒,但是其中的toString不会显示毫秒),直接调用无参构造就行,输出的时间是国外那种形式的日期
如果用有参构造,传入的参数是毫秒,获取的时间是自 1970年1月1日0时 加上参数的时间
日期怎么格式化?即将日期类型Date,按照指定的格式进行转换,转换成一定格式的日期字符串String
SimpleDateFormat是java.text包下的。专门负责日期的格式化
yyyy 年(年是4位的)
MM月 (月是2位)
dd日 (日是2位)
HH时
mm分
ss秒
SSS毫秒 (毫秒3位,最高999,1000毫秒等于1秒)
注意:在日期格式中,除了给定的字符不能随便写,其他随意组织
Date nowTime = new Date(); //先获取系统当前时间
System.out.println(nowTime);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E"); //更改格式
String now = sdf.format(nowTime); //调用format方法,将Date改为String
System.out.println(now);
怎么将String类型转换为Date类型?
String time = "2008-08-08 08:08:08 888";
//构造方法中的格式必须和String time的日期格式相同
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
Date dateTime = sdf2.parse(time); //调用parse方法
System.out.println(dateTime);
获取自1970年1月1日 00:00:00 000到当前系统时间的总毫秒数
System.currentTimeMillis(); //可以统计运行时长 北京在东八区,所以从8点开始计算
//系统当前时间
Date nowTime = new Date();
System.out.println(nowTime); //Sat May 08 19:51:02 CST 2021
//Date转换成字符串
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
String now = sdf.format(nowTime);
System.out.println(now); //2021-05-08 19:51:02 周六
//字符串转换成Date
String time = "2008-08-08 08:08:08 888";
//构造方法中的格式必须和String time的日期格式相同
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
Date dateTime = sdf2.parse(time);
System.out.println(dateTime); //Fri Aug 08 08:08:08 CST 2008
Date time = new Date(1);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String stf = sdf.format(time);
System.out.println(stf); //1970-01-01 08:00:00 001
long nowTimeMills = System.currentTimeMillis();
System.out.println(nowTimeMills); //1620474799045
//统计运行时长
long begin = System.currentTimeMillis();
for(int i = 0; i < 1000000000; i++){}
//System.out.println(i);
long end = System.currentTimeMillis();
System.out.println(end - begin); //3
暂时总结System
System.out 【out是System类的静态变量】
System.out.println() 【println()方法不是System类的,是PrintStream类的方法】
System.gc() 建议启动垃圾回收器
System.exit(0) 退出JVM
System.currentTimeMillis()
数字相关类
java.text.DecimalForamt 专门负责数字格式化的
DecimalFormat df = new DecimalForamt(“数字格式”);
数字格式有哪些?
# 代表任意数字
, 代表千分位
. 代表小数点
0 代表不够时补零
例子:###,###.##
java.math.BigDemical;
BigDemical 属于大数据,精度极高,不属于基本数据类型,属于java对象,这是一个类,专门用在财务软件中
DecimalFormat df = new DecimalFormat("###,###.0000000");
String s = df.format(12234.5656);
System.out.println(s); //12,234.5656000
BigDecimal v1 = new BigDecimal(100);
BigDecimal v2 = new BigDecimal(200);
System.out.println(v1.add(v2)); //300
随机数:
java.util.Random;
//产生任意数
Random random = new Random();
int num1 = random.nextInt(); //nextInt无参数,无边界产生随机数
int num1 = random.nextInt(101); //产生0-100之间的随机数,不能产生101
//nextInt翻译为:下一个int类型数据是101,表示只能取到100
Random random = new Random();
//生成五个不同的随机数,放在数组中
int[] array = new int[5];
for(int t = 0; t < 5; t++){
array[t] = -1;
System.out.println(array[t]);
}
boolean flag= false;
for(int i = 0; i < 5; i++){
int num = random.nextInt(5);
System.out.println("生成的随机数"+num);
// array[i] = num;
for(int j = 0; j < 5; j++){
// if(i == j)
// continue;
if(num == array[j]){
// array[i] = -1;
i--;
flag = true;
break;
}
flag = false;
}
if(flag == false)
array[i] = num;
}
for(int x = 0; x < 5; x++)
System.out.println(array[x]);
//结果
-1
-1
-1
-1
-1
生成的随机数2
生成的随机数2
生成的随机数0
生成的随机数1
生成的随机数3
生成的随机数0
生成的随机数0
生成的随机数4
2
0
1
3
4
枚举
枚举:当一个方法执行结果超过两种情况,并且是一枚一枚可以列举出来的时候,建议返回值类型设计为枚举类型。
枚举编译之后也是生成class文件
枚举也是一种引用数据类型
枚举中的每一个值可以看做是常量
枚举类型语法:
enum 枚举类型名{
枚举值1,枚举值2,枚举值3(全部大写)
}
****switch语句支持枚举类型
public class EnumTest {
public static void main(String[] args) {
Result r = divide(10,0);
System.out.println(r == Result.FAIL? "计算失败":"计算成功"); //计算失败
switch (Season.AUTUMN){
case SPRING:
System.out.println("春天放风筝");
break;
case SUMMER:
System.out.println("夏天大太阳");
break;
case AUTUMN:
System.out.println("秋天大丰收"); //√
break;
case WINTER:
System.out.println("冬天下大雪");
break;
}
}
public static Result divide(int a, int b){
try{
int c = a / b;
return Result.SUCCESS;
} catch (Exception e){
return Result.FAIL;
}
}
}
enum Result{
SUCCESS,FAIL
}
enum Season {
SPRING,
SUMMER,
AUTUMN,
WINTER
}
异常
程序执行过程中发生了不正常的情况,而这种不正常的情况叫做:异常
java语言是很完善的语言,提供了异常的处理方式,程序在执行过程中出现了不正常的情况,java把该异常信息打印输出到控制台,供程序员参考,程序员看到异常信息之后,可以对程序进行修改,让程序更加健壮。
异常信息是JVM打印的
异常的作用:增强程序的健壮性
在java中异常以类的形式存在,每一个异常类都可以创建异常对象
实际上JVM执行到不正常处时,会new异常对象,并且JVM将new的异常对象抛出,打印到控制台上
异常在现实生活中:
火灾(异常类):
小明家着火了(异常对象)
小芳家着火了(异常对象)
java的异常处理机制
1.异常的继承结构是怎样的?
我们可以使用UML图来描述一下继承结构
画UML图有很多工具,例如:Rational Rose(收费的)、starUML等..
2.什么是UML?有什么用?
UML是一种统一建模语言
一种图标式语言(画图的)
UML不是只有java使用,只要是面向对象的编程语言,都有UML
一般画UML图的都是软件架构师或者说是系统分析师,软件设计人员使用UML
在UML图中可以描述类和类的关系,程序执行的流程,对象的状态等
Object下有Throwable(可抛出的)
Throwable下有两个分支:Error 和 Exception
不管是错误,还是异常,都是可抛出的
所有的错误只要发生,java程序只有一个结果,那就是终止程序的执行。退出JVM,错误是不能处理的
异常可以处理,异常包括两个分支:
第一个是Exception的直接子类(ExceptionSubClass),叫做编译时异常。编译时异常是表示必须在编写程序的时候,预先对这种异常进行处理,如果不处理,编译器报错
第二个是运行时异常:RuntimeException。运行时异常,在编写程序阶段可以处理也可以选择不处理
编译时异常和运行时异常,都是发生在运行阶段,编译阶段异常是不会发生的
(******)所有异常都是在运行阶段发生的,因为只有程序运行阶段才可以new对象,因为异常的发生就是new异常对象
编译时异常和运行时异常的区别?
编译时异常一般发生的概率比较高
运行时异常一般发生的概率比较低
编译时异常又被称为受检异常(CheckedException),还叫做受控异常
运行时异常又称为:未受检异常(UnCheckedException),或者非受控异常
假设java中没有对异常进行划分,没有分为:编译时异常和运行时异常,所有的异常都需要在编写阶段对其进行预处理,将是怎样的结果?
首先,如果这样的话,程序肯定是绝对安全的
但是程序员编写程序太累,代码到处都是处理异常的代码
java中对异常的处理有两种方式:
第一种方式:在方法声明的位置上,使用throws关键字,抛给上一级
谁调用我,我就抛给谁
第二种方式:使用try...catch语句进行异常的捕捉
这件事发生了,谁也不知道,因为我给抓住了
思考:
异常发生之后,如果我选择了上抛,抛给了我的调用者,调用者需要对这个异常继续处理,那么调用者处理这个异常也有两种处理方式
注意:如果异常发生之后一直上抛,最终抛给了main方法,main方法继续上抛,抛给了调用者JVM,JVM知道这个异常发生,只有一个结果,终止程序的执行
处理异常的第一种方式:
在方法声明的位置上使用throws关键字抛出,谁调用我这个方法,我就抛给谁,抛给调用者来处理
throws后面也可以写多个异常,可以用逗号隔开
除了抛当前的异常,也可以抛出该异常的父类异常
一般不建议在main方法上使用throws,因为这个异常如果真正的发生了,一定会抛给JVM,JVM只有终止。(异常处理机制的作用就是增强程序的健壮性,即异常发生了也不影响程序的执行,所以main方法中的异常建议时使用try..catch进行捕捉)
第二种:捕捉
使用try...catch语句对异常进行捕捉,异常抛到此处,不再上抛了
在catch分支中干什么?处理异常
注意:
只要异常没有捕捉,采用上报的方式,此方法的后续代码不会执行
一个方法体当中的代码出现异常之后,如果上报的话,此方法结束
另外需要注意,try语句块中的某一行出现异常,该行后面的代码不会执行
1.catch后面的小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型
2.catch可以写多个,建议精确处理一个个异常,这样有利于程序的调试
3.catch写多个的时候,从上到下,必须遵守从小到大的原则
4.catch在JDK8之后可以写或者关系,例如
catch(FileNotFoundException | NullPointerException)
5.finally
第一:在finally字句中的代码是最后执行的,并且一定会执行的,即使try语句块中的代码出现了异常,即使try中有return(但是有System.exit(0);退出JVM就不会执行了)
必须和try...catch一起出现
第二:finally通常使用在哪些情况下?
通常在finally语句块中完成资源的释放/关闭
因为finally中的代码比较有保障
第三:try和finally可以连用,没有catch也可以
上报和捕捉怎么选择?如果希望调用者处理,就上报;其他情况使用捕捉
异常对象有两个重要的方法
获取异常简单的描述信息:
String msg = exception.getMessage();
打印异常追踪的堆栈信息:(常用)
java后台打印异常堆栈追踪信息的时候,采用了异步线程的方式打印的
exception.printStackTrace();
怎么看异常追踪的堆栈信息,来快速调试程序?
异常追踪信息从上往下一行一行看
但是需要注意的是:SUN公司写的就不要看了,主要看自己写的代码上
面试题(特殊情况)
例子见ExceptionTest06:
public static void main(String[] args) {
int result = m();
System.out.println(result);
}
public static int m(){
int i = 100;
try{
return i;
}finally {
i++;
}
} //输出100
反编译之后的代码可以解释:
public static int m(){
int i = 100;
int j = i;
i++;
return j;
}
java语法规则(有一些规则是不能破坏的):
方法体中的代码必须遵循自上而下顺序依次逐行执行(亘古不变的语法)
return语句一旦执行,整个方法必须结束
final finally fianlize 有什么区别?
final是一个关键字,修饰的变量表示最终的不变的,修饰的方法不可覆盖,修饰的类不能继承
fianlly也是一个关键字,和try联用,使用在异常处理机制中,在finally语句块中的代码是一定会执行的
fianlize()是Object中的一个方法,作为方法名出现,是一个标识符
fianlize()方法是由垃圾回收器GC负责调用的
自定义异常
1.SUN提供的JDK内置的异常肯定是不够用的,实际开发中和业务挂钩
2.怎么自定义异常?(死记硬背)
第一步:编写一个类继承Exception和RuntimeException
第二步:提供两个构造方法,一个有参带有String参数,一个无参
手动抛异常
语法:
throw new 异常对象;
###之前知识点:
重写之后的方法不能比重写之前的方法抛出更多的(更宽泛)的异常,可以更少
特殊点:父类不抛异常,子类可以抛出运行异常RuntimeException
//通过异常类实例化异常对象
NullPointerException npe = new NullPointerException("我发生了异常");
System.out.println(npe);
int a = 10;
int b = 0;
//实际上JVM在执行到此处的时候,会new异常对象: new ArithmeticException("/by zero");
//并且JVM将new的异常对象抛出,打印到控制台上
int c = a / b;//发生了异常
//Exception in thread "main" java.lang.ArithmeticException: / by zero
System.out.println(c);
//异常处理两种方式
public class ExceptionTest02 {
/*public static void main(String[] args) throws ClassNotFoundException {
//由于ClassNotFoundException是一个编译时异常,没有处理编译器报错
//第一种处理方式:在方法声明的位置继续上抛,抛给调用者
doSome();
}
*/
public static void main(String[] args) {
//第二种处理方式是try..catch进行捕捉
try {
doSome();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void doSome() throws ClassNotFoundException{
System.out.println("我在做什么");
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ExceptionTest03 {
public static void main(String[] args){
System.out.println("main begin");
try {
m1();
//m1出异常,下面的输出就不执行了,跳到catch语句中执行
System.out.println("hello world");
} catch (FileNotFoundException e) {
//这个分支中可以使用e引用,e引用保存的内存地址是那个new出来异常对象的内存地址
//catch是捕捉异常之后走的分支
//e.printStackTrace();
System.out.println(e.getMessage());
//System.out.println("找不到该文件");
}
System.out.println("main end");
}
//throws FileNotFoundException的父类IOException
private static void m1() throws FileNotFoundException{
System.out.println("m1 begin");
m2();
System.out.println("m1 end");
}
private static void m2() throws FileNotFoundException{
System.out.println("m2 begin");
m3();
System.out.println("m2 end");
}
private static void m3() throws FileNotFoundException {
//创建一个输入流对象,该流指向一个文件
/* 这里编译报错的原因是什么?
第一:这里调用了一个构造方法FileInputStream(String name)
第二:这个构造方法的声明位置上有:throws FileNotFoundException
第三:通过类的继承机构看到:FileNotFoundException 父类是 IOException,IOException的父类是Exception
最终得知,FileNotFoundException是编译时异常
* */
new FileInputStream("C:\\\\Users\\\\清风\\\\Desktop\\\\JAVA学习\\\\001-JavaSE课堂笔记+思维导图\\\\07-JavaSE进阶每日复习与笔记\\\\day27课堂笔记.txt");
System.out.println("如果出异常,这里不会执行");
}
}
----------------------
//无异常输出如下:
main begin
m1 begin
m2 begin
如果出异常,这里不会执行
m2 end
m1 end
hello world
main end
--------------------
有异常输出如下:
main begin
m1 begin
m2 begin
C:\\Users\\清风\\Desktop\\JAVA学习\\day27课堂记.txt (系统找不到指定的文件。)
main end
try{
System.out.println(100/0);
FileInputStream fis = new FileInputStream("C:\\\\Uers\\\\清风\\\\Desktop\\\\JAVA学习\\\\day27课堂笔记.txt");
System.out.println(100/0);
}catch (FileNotFoundException e){
System.out.println("文件不存在");
}catch (ArithmeticException e){
System.out.println("除数不能为0"); //输出:除数不能为0
}
//这里只是new了异常对象,并没有抛出,JVM会认为这是一个普通的Java对象
NullPointerException e = new NullPointerException("空指针异常");
//获取异常的简单描述信息:这个信息实际上就是构造方法上面String参数
String msg = e.getMessage();
System.out.println(msg); //空指针异常
//打印异常堆栈信息
//以下代码:先输出try0000000,再输出final,再执行return
try{
System.out.println("try00000000");
return;
}finally {
System.out.println("fianl");
}
//下面程序,先输出101,再输出100
public static void main(String[] args) {
int result = m();
System.out.println(result); //100
}
public static int m(){
int i = 100;
try{
return i;
}finally {
i++;
System.out.println(i); //101
}
}
以上是关于Java学习13(异常)的主要内容,如果未能解决你的问题,请参考以下文章
PCL异常处理:pcl 1.8.13rdpartyoostincludeoost-1_64oost ypeofmsvc ypeof_impl.hpp(125): error(代码片段
java.lang.NullPointerException: Attempt to invoke virtual method ‘int android.database.sqlite异常(代码片段