一篇文章带你爆杀Java-异常、随机数、包装类、日期类!

一、知识点

异常、随机数、包装类、日期类。

二、目标

  1. 掌握异常机制。

  2. 理解try...catch代码块。

  3. 掌握常用工具类的使用。

三、内容分析

  1. 重点

    • 异常、包装类、日期类。

  2. 难点

    • 异常的理解。

    • 包装的理解。

四、内容

1、异常

1.1 概述

正如“人无完人”一样,程序也不是完美的,它总会存在这样那样的问题,而有些问题并不是能够通过程序员开发更好的代码来解决的,如果我们忽视它,可能就会造成程序的终止,甚至是系统的崩溃。因此,我们需要想办法来合理的解决它,这就是Java中异常的由来。

异常是指程序在执行过程中,出现的非正常情况。比如:空的引用、数组下标越界、内存溢出错误、读取文件不存在、网络断开等。

一般来说有两种方法来处理异常:

  1. 遇到错误就终止程序运行;

  2. 开发人员在编写程序的时候考虑到可能出现的非正常情况,提前做好处理(这个是最好的,不过也是不容易的)。

1.2 Java中的异常

Java是面向对象的语言,异常被当成了一个对象来处理。其根类是java.lang.Throwable类,Throwable类又分成了两个子类,即Error和Exception。这是异常的两个大类,他们分别代表了两种情况:

  1. Error:不能处理的错误,这是系统内部的错误,运行时报错,属于系统问题。一般发生这种异常,JVM会选择终止程序,开发人员需要提前避免。

  2. Exception:可以处理的异常,这是比较常见的异常,开发人员可以根据Java提供的类和问题对这类异常进行处理。

 

 

1.3 Error

对于严重错误Error,没有办法处理,只能做到提前避免。常见的Error有:StackOverflowError(栈溢出错误)和OutOfMemoryError (内存溢出错误)。

Java中堆是用来存储对象实例的,因此如果我们不断地创建对象, 并且对象没有被垃圾回收, 那么当创建的对象过多时, 会导致内存不足, 进而引发 OutOfMemoryError 异常。

1.4 Exception

一般来说,我们所说的异常就是指Exception,因为这类异常一旦出现,我们就要对代码进行更正,修复程序进行处理。

根据编译时期还是运行时期去检查异常,可以将Exception分为:

  1. 编译时期异常:checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败(开发工具会提示),如文件找不到异常等。所以编译时期异常我们必须处理,否则编译不通过。

  2. 运行时期异常:runtime异常。在运行时期,检查异常。在编译时期,运行异常不会被编译器检测到(开发工具不会提示,只有代码运行的时候才会报异常),如空指针异常,类型转换异常,数字操作异常等。

public static void main(String[] args) {

    // 编辑器会直接报错,这里就是编译时期异常
    // Unhandled exception: java.io.FileNotFoundException,即未处理异常。
    FileInputStream inputStream = new FileInputStream("java笔记.txt");

    String s1 = null;
    System.out.println(s1.length()); // 空指针异常NullPointerException
    
    Object object = new Object();
    String s2 = (String) object; // 类型转换异常ClassCastException
    
    int i = 10 / 0; // 数字操作异常ArithmeticException
}
1.5 异常的处理

程序异常时非常常见的,我们可以怎么处理呢?

处理异常有三种方式:throw(抛出)、throws(声明,往上抛)、try-catch(捕获)代码块

  1. throw

Java程序出现异常时会生成一个异常类对象,该异常对象将被提交给Java运行时系统,这个过程称为抛出(throw)异常。

  • 自动生成:程序运行过程中,虚拟机检测到程序发生了问题,如果在当前代码中没有找到相应的处理程序,就会在后台自动创建一个对应异常类的实例对象并抛出,自动抛出。

  • 手动创建:Exception exception = new Exception();创建好的异常对象不抛出对程序没有任何影响,和创建一个普通对象一样,但是一旦throw抛出,就会对程序运行产生影响了,程序就会中断执行。

// 自动生成异常
public static void main(String[] args) {

    int arr[] = { 10, 20, 30, 40 };
    int index = 4;

    // 运行之后控制台会报异常,下标越界了。
    // 我们写相应的异常处理程序代码,由虚拟机自动检测创建异常对象自动抛出。
    System.out.println(getElement(arr, index));

}

// 函数:获取数组对应下标的元素值
public static int getElement(int arr[], int index) {
    return arr[index];
}
// 手动生成异常
public static void main(String[] args) {

    int arr[] = { 10, 20, 30, 40 };
    int index = 4;

    System.out.println(getElement(arr, index));

}

// 函数:获取数组对应下标的元素值
// 考虑到数组可能出现的异常情况,我们手动做了处理
public static int getElement(int arr[], int index) {

    if(arr == null) {
        throw new NullPointerException("数组为空!");
    }

    if(index < 0 || index > arr.length - 1) {
        throw new ArrayIndexOutOfBoundsException("下标越界!");
    }

    return arr[index];
}

     2.throws 

Java程序出现异常时将问题标识出来,报告给调用者,让调用者去处理。关键字throws运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(如果调用者不处理,则接着抛出异常,甩锅)。

public static void main(String[] args) {
    // 调用test方法编辑器会提示报错,因为test方法有异常但是不处理,抛了出来
    test();
}

public static void test() throws FileNotFoundException {

    // 这里会出现异常,但是我们不处理,把异常直接throws
    FileInputStream fileInputStream = new FileInputStream("java笔记.txt");

}

     3.try...catch 

try-catch就是捕获异常,可以对出现的异常进行指定方式的处理。(主动处理,不甩锅)

语法:

try {
    // 可能出现异常的代码
} catch(异常类型1 e) {
    // 当try里面发生异常类型1对应的异常时触发
    // 这里是触发异常之后要执行的代码
} catch(异常类型2 e) {
    // 当try里面发生异常类型2对应的异常时触发
    // 这里是触发异常之后要执行的代码
}
...

示例:

public static void main(String[] args) {

   try {
        int i  = 10 / 0;
        // String str = null;
        // str.length();
   } catch (ArithmeticException e) {
        // 出现数学异常时,执行这里的代码
        System.out.println("数学异常");
   } catch (NullPointerException e) {
        // 出现空指针异常时,执行这里的代码
        System.out.println("空指针异常");
   }

    // 这里的代码还是会执行,使用try...catch指定处理异常,程序不会中断
    System.out.println("1");
}

      4.finally代码块 

保证出现异常之后也会执行的代码。当在try语句块中打开了一些物理资源(磁盘文件/网络连接/数据库连接等),我们都得在使用完之后关闭打开的资源。

语法:

try {

} catch(...) {

} finally {
    
}

示例:

public static void main(String[] args) {

    try {
        System.out.println("读取文件");

        System.out.println("操作文件");

        // 关闭文件的代码不适合写这里,因为读取文件之后,在操作文件的过程中可能出现异常,导致关闭文件的代码不执行。
        // System.out.println("关闭文件");
    } catch (Exception e) {
        System.out.println("出现异常");
    } finally {
        // 把关闭文件的代码放在这里,不管try里面有没有出现异常,都会执行这里的代码。
        System.out.println("关闭文件");
    }
}
1.6 自定义异常

异常的情况有非常多,因此Java内部并不能把这些都包含进去,这就需要开发人员根据自己的实际业务情况进行自定义异常。比如年龄负数问题,考试成绩负数问题等等。

接下来介绍如何自定义异常:

自定义类继承RuntimeException。

public class AgeLessThan0Exception extends RuntimeException{

	public AgeLessThan0Exception() {
		super("年龄是负数!");
	}
	
}
public static void main(String[] args) {

    int age = -10;

    if(age < 0) {
        // 控制台会打印【AgeLessThan0Exception: 年龄是负数!】
        throw new AgeLessThan0Exception();
    }

}

2、随机数

随机数在常用业务中也很常用,比如抽奖、随机点名等。

Random random = new Random();
random.nextInt(); // int范围内产生一个随机数
random.nextInt(10); // 返回0~9之间的随机数
// 固定的随机数列
Random random = new Random(10);
for(int i = 0; i < 10; i++) {
    System.out.println(random.nextInt());
}

3、日期类

在日常的开发工作当中,我们经常需要用到日期相关的类用来操作时间相关的数据。

3.1 Date

最基础的一个日期类。

Date date = new Date();
// Date重写了toString方法,打印出来的是一个外国人习惯的日期格式字符串。
System.out.println(date);
// 时间戳:获取1970.01.01到现在过去的毫秒数
System.out.println(date.getTime());

// 有很多已经被弃用了,如果要获取年月日时分秒可以使用日历类Calendar
System.out.println(date.getYear());
System.out.println(date.getMonth());
3.2

日历类。

// 获取日历对象
Calendar c = Calendar.getInstance();

System.out.println("获取年份:"+c.get(Calendar.YEAR));
System.out.println("获取月份:"+(c.get(Calendar.MONTH)+1)); //月份0~11
System.out.println("获取日期(今天是该月的第几天):"+c.get(Calendar.DAY_OF_MONTH));
System.out.println("获取小时数(12小时制):"+c.get(Calendar.HOUR));
System.out.println("获取小时数(24小时制):"+c.get(Calendar.HOUR_OF_DAY));
System.out.println("获取分钟数:"+c.get(Calendar.MINUTE));
System.out.println("获取秒钟数:"+c.get(Calendar.SECOND));
System.out.println("获取毫秒数:"+c.get(Calendar.MILLISECOND));
System.out.println("获取当前是该年中的第几天:"+c.get(Calendar.DAY_OF_YEAR));
System.out.println("获取今天是周几:"+c.get(Calendar.DAY_OF_WEEK));

//将月份设置到6月份
c.set(Calendar.MONTH, 5);
// 将年份+1
c.add(Calendar.YEAR, 1);
// 返回Date数据格式的时间
c.getTime();
3.3 SimpleDateFormat

格式化日期类。

// SimpleDateFormat(格式可以查看文档)
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 将当前日期转化成yyyy-MM-dd HH:mm:ss格式的字符串
String date = simpleDateFormat.format(new Date());
System.out.println(date);

// 将日期格式的字符串转化成Date对象
    String dateStr = "2000-01-01 12:00:00";
    try {
        Date date2 = simpleDateFormat.parse(dateStr);
        System.out.println(date2);
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

4、包装类

Java里面8个基本数据类型都有相应的类,这些类叫做包装类。

Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。

把基本数据类型转换成类,包装类提供了很多的方法给我们使用(查看JDK文档)。

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean
// 这里的i是一个对象,具有自己的属性和方法
Integer i = new Integer(10);
System.out.println(i); // 10
4.1 自动拆箱

包装类转换成基本数据类型的过程就是拆包装,英文对应于unboxing,中文翻译为拆箱。

自动拆箱:就是将包装类自动转换成对应的基本数据类型。

// 包装类转基本数据类型的方法
Integer i1 = new Integer(100);
// 第一种
int i2 = i1.intValue();
// 第二种:自动拆箱,自动调用intValue()方法
int i3 = i1;
4.2 自动装箱

包装类是对基本类型的包装,所以,把基本数据类型转换成包装类的过程就是打包装,英文对应于boxing,中文翻译为装箱。

自动装箱: 就是将基本数据类型自动转换成对应的包装类。

// 基本数据类型转包装类的方法

int i4 = 100;

// 第一种
Integer i5 = Integer.valueOf(10);
// 第二种: 自动装箱,自动调用了Integer.valueOf()方法
Integer i5 = i4;
4.3 思考
int i6 = 100;
Integer i7 = new Integer(100);
Integer i8 = new Integer(100);
Integer i9 = 200;
Integer i10 = 200;
Integer i11 = 100;
Integer i12 = 100;

System.out.println(i6 == i7);
System.out.println(i7 == i8);
System.out.println(i9 == i10);
System.out.println(i9.intValue() == i10.intValue());
System.out.println(i11 == i12);


System.out.println(i6 == i7); // true 包装类与基本类型比较的时候会将包装类拆箱成基本类型进行比较。
System.out.println(i7 == i8); // false  new出两个新的地址
System.out.println(i9 == i10); // false 自动装箱,调用了valueOf() 把int转化为对象 -128~127
System.out.println(i9.intValue() == i10.intValue()); // true
System.out.println(i11 == i12); // true 常量池会初始化-128到127的值,只会保留一个地址的值

五、小结

介绍了Java的异常处理机制,以及常用工具类的用法。重点掌握try...catch的用法,熟悉常用工具类内置方法的作用,提高查阅jdk文档的能力。

六、练习

  1. 获取100天后的时间,并且打印,格式(yyyy-MM-dd HH:mm:ss)。

  2. 赌数游戏。

提供三个1-6的随机数,作为掷骰子得到的点数。如果各个点数相同,则为豹子。 如果三个骰子点数和,小于或等于9,则为“小”。 如果三个骰子点数和,大于9,则为“大”。 用户随机选择:押大、押小或者押豹子。通过判断,输出客户是否押正确。

以上就是本文内容,相信你学完已经爆杀了! 

  • 29
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值