总结:
(第一次在学校写作业,感觉激情来了,O(∩_∩)O~~)
Java异常机制主要依赖于try、catch、finally、throw、throws五个关键字。
1.try:它里面放置可能引发异常的代码
2.catch:后面对应异常类型和一个代码块,用于表明该catch块用于处理这种类型的代码块,可以有多个catch块。
3.finally:主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件),异常机制总是保证finally块总是被执行。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者 throw等终止方法的语句,则就不会跳回执行,直接停止。
在以下4种特殊情况下,finally块不会被执行:
1)在finally语句块中发生了异常。
2)在前面的代码中用了System.exit()退出程序。
3)程序所在的线程死亡。
4)关闭CPU。
4.throw:用于抛出一个实际的异常,可以单独作为语句使用,抛出一个具体的异常对象。
5.throws:用在方法签名中,用于声明该方法可能抛出的异常。
作业
1. java中用来抛出异常的关键字是什么?
throws,throw,try,catch,finally
2. 异常和Error的区别?
error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。 exception表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。
3. 什么是异常?
异常指不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程。Java通过API中Throwable类的众多子类描述各种不同的异常。因而,Java异常都是对象,是Throwable子类的实例,描述了出现在一段编码中的错误条件。当条件生成时,错误将引发异常。
4. 什么类是所有异常类的父类
Throwable:有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。
5. java虚拟机能自动处理的异常是什么?
运行时异常:都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。
6. Try-catch-finally的执行过程
try {
// 可能会发生异常的程序代码
} catch(Type1 id1) {
// 捕获并处理try抛出的异常类型Type1
} catch(Type2 id2) {
// 捕获并处理try抛出的异常类型Type2
} finally{
// 无论是否发生异常,都将执行的语句块
}
7. 常见的异常?你的理解。
(1).SQLException:该异常提供关于数据库访问错误或其他错误的信息。checked异常(编译时异常)
(2).RuntimeException 是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类Runtime异常(运行时异常)
(3).IOException:此类为异常的通用类,它是由失败的或中断的 I/O 操作生成的。checked异常(编译时异常)
8. final, finally, finalize的区别。
final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
内部类要访问局部变量,局部变量必须定义成final类型,例如,一段代码……
finally是异常处理语句结构的一部分,表示总是执行。
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用
9. Java中的异常处理机制的简单原理和应用。
异常是指java程序运行时(非编译)所发生的非正常情况或错误,与现实生活中的事件很相似,现实生活中的事件可以包含事件发生的时间、地点、人物、情节等信息,可以用一个对象来表示,Java使用面向对象的方式来处理异常,它把程序中发生的每个异常也都分别封装到一个对象来表示的,该对象中包含有异常的信息。
Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,所有异常的根类为java.lang.Throwable,Throwable下面又派生了两个子类:Error和Exception,Error表示应用程序本身无法克服和恢复的一种严重问题,程序只有死的份了,例如,说内存溢出和线程死锁等系统问题。Exception表示程序还能够克服和恢复的问题,其中又分为系统异常和普通异常,系统异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);普通异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常后,程序不应该死掉。
java为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须try..catch处理或用throws声明继续抛给上层调用方法处理,所以普通异常也称为checked异常,而系统异常可以处理也可以不处理,所以,编译器不强制用try..catch处理或用throws声明,所以系统异常也称为unchecked异常。
提示答题者:就按照三个级别去思考:虚拟机必须宕机的错误,程序可以死掉也可以不死掉的错误,程序不应该死掉的错误;
10.运行时异常与一般异常有何异同?
异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。
1.编写一个员工类,
(1) 有属性:
编号,姓名,年龄,工资,身份证号码,员工人数,员工工资总额
(2) 有构造器:
构造器1:设置编号,年龄,姓名;如果年龄小于18,抛出年龄低异常;如果年龄大于60
抛出年龄高异常,如果姓名为null或为空字符串,抛出空异常。
构造器2:设置工资,设置身份证号码;如果工资低于600,抛出工资低异常。
(3) 有方法
增加工资 addSalary(double addSalary),抛出工资高异常,当增加后的工资大于员工工资总额时,抛出此异常。
减少工资 minusSalary(double minusSalary), 抛出工资低异常,当减少后的工资低于政府最低工资时,抛出工资低异常。
显示员工工资总额方法:showTotalSalary(),抛出空异常,当工资总额为0时,抛出此异常。
显示员工人数:voidshowTotalEmployee(),抛出空异常。当员工人数为0时,抛出此异常。
package com.jiale.demo01;
public class HeightAgeException extends Exception {
public HeightAgeException() {}
public HeightAgeException(Stringmessage) {
// TODO自动生成的构造函数存根
super(message);
}
}
package com.jiale.demo01;
public class LowAgeException extends Exception {
public LowAgeException() {}
public LowAgeException(String message) {
// TODO自动生成的构造函数存根
super(message);
}
}
package com.jiale.demo01;
public class HighSalaryException extends Exception {
public HighSalaryException() {}
public HighSalaryException(String message) {
// TODO自动生成的构造函数存根
super(message);
}
}
package com.jiale.demo01;
public class LowSalaryException extends Exception {
public LowSalaryException() {}
public LowSalaryException(String message) {
// TODO自动生成的构造函数存根
super(message);
}
}
package com.jiale.demo01;
public class NullException extends Exception {
public NullException() {}
public NullException(String message) {
// TODO自动生成的构造函数存根
super(message);
}
}
package com.jiale.demo01;
public class Employee {
private String number;
private String name;
private int age;
private int salary;
private String IDnumber;
private int totalEmployee = 10;
private int totalSalary = 10000;
/**
* 构造器
* @throws NullException
* @throws LowAgeException
* @throwsHeightAgeException
*/
public Employee(String number, String name, int age) throws NullException, LowAgeException, HeightAgeException {
// TODO自动生成的构造函数存根
this.number = number;
this.name = name;
this.age = age;
if(name == ""){
throw new NullException("空异常!");
}
if(age < 18){
throw new LowAgeException("年龄太小异常!");
}
if(age > 80){
throw new HeightAgeException("年龄太大异常!");
}
}
public Employee(int salary, String IDnumber) throws LowSalaryException {
// TODO自动生成的构造函数存根
this.salary = salary;
this.IDnumber = IDnumber;
if(salary < 600){
throw new LowSalaryException("工资太低异常!");
}
}
/**
* 所有属性的set和get方法
* @return
*/
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public String getIDnumber() {
return IDnumber;
}
public void setIDnumber(String iDnumber) {
IDnumber = iDnumber;
}
public int getTotalEmployee() {
return totalEmployee;
}
public void setTotalEmployee(int totalEmployee) {
this.totalEmployee = totalEmployee;
}
public int getTotalSalary() {
return totalSalary;
}
public void setTotalSalary(int totalSalary) {
this.totalSalary = totalSalary;
}
/**
* 异常处理方法
* @param addSalary
* @return
* @throwsHeightAgeException
*/
public double addSalary(double addSalary) throws HeightAgeException{
if(addSalary+salary > totalSalary){
throw new HeightAgeException("工资太高异常!");
}
return addSalary+salary;
}
public double minusSalary(double minusSalary) throws LowSalaryException{
if(salary-minusSalary < 600){
throw new LowSalaryException("工资太低异常!");
}
return salary-minusSalary;
}
public void showTotalSalary() throws NullException{
if(totalSalary == 0){
throw new NullException("空异常!");
}
System.out.println("工资总额:"+totalSalary);
}
public void showTotalEmployee() throws NullException{
if(totalEmployee == 0){
throw new NullException("空异常!");
}
System.out.println("员工人数:"+totalEmployee);
}
}
package com.jiale.demo01;
public class demo01 {
public static void main(String[] args) {
// TODO自动生成的方法存根
try {
Employee em1 = new Employee("001", "张三", 19);
Employee em2 = new Employee(9000, "140223199505643545");
em1.showTotalEmployee();
em2.showTotalSalary();
/**
* 员工人数:10
工资总额:10000
com.jiale.demo01.NullException:空异常!
at com.jiale.demo01.Employee.showTotalEmployee(Employee.java:115)
at com.jiale.demo01.demo01.main(demo01.java:15)
*/
// em1.setTotalEmployee(0);
// em2.setTotalSalary(0);
// em1.showTotalEmployee();
// em2.showTotalSalary();
em2.addSalary(1100.0);
em2.minusSalary(8500);
} catch (NullException | LowAgeException | HeightAgeException |LowSalaryException e) {
// TODO自动生成的 catch 块
e.printStackTrace();
}
}
}
运行结果:
员工人数:10
工资总额:10000
com.jiale.demo01.HeightAgeException: 工资太高异常!
atcom.jiale.demo01.Employee.addSalary(Employee.java:97)
atcom.jiale.demo01.demo01.main(demo01.java:26)
2.编写一道自定义异常。
public class CustomException extendsException { //或者继承任何标准异常类
publicCustomException() {} //用来创建无参数对象
public CustomException(Stringmessage) { //用来创建指定参数对象
super(message); //调用超类构造器
}
}
反射与泛型
1. Java反射机制的作用
ava反射机制提供如下功能:
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判段任意一个类所具有的成员变量和方法
在运行时调用任一个对象的方法
在运行时创建新类对象
在使用Java的反射功能时,基本首先都要获取类的Class对象,再通过Class对象获取其他的对象。
2. 什么是反射?什么是泛型?
Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。
Java反射机制容许程序在运行时加载、探知、使用编译期间完全未知的classes。
换言之,Java可以加载一个运行时才得知名称的class,获得其完整结构。
泛型是Java SE1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。
3. Java的泛型是如何工作的 ? 什么是类型擦除 ?
Java的泛型是伪泛型。为什么说Java的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉。正确理解泛型概念的首要前提是理解类型擦出(type erasure)。
Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。
如在代码中定义的List<object>和List<String>等类型,在编译后都会编程List。JVM看到的只是List,而由泛型附加的类型信息对JVM来说是不可见的。Java编译器会在编译时尽可能的发现可能出错的地方,但是仍然无法避免在运行时刻出现类型转换异常的情况。类型擦除也是Java的泛型实现方法与C++模版机制实现方式之间的重要区别。
4. 面试题:什么是泛型?泛型的优点?jdk各版本之间的区别?
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
Java语言引入泛型的好处是安全简单。
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。