第7篇-JAVA面向对象Ⅲ

2022-03-11 11:31 更新
  • 每篇一句 :任何值得去的地方,都没有捷径
  • 初学心得: 温故而知新
  • (笔者:JEEP/711)[JAVA笔记 | 时间:2017-04-09| JAVA面向对象 Ⅲ]

目录导航

[TOC]

1.JAVA基本包装类型


| 基本数据类型 | 包装类 |
| :-------- | --------: |
| byte | Byte |
| short | Short |
| int | Integer |
| char | Character |
| float | Float |
| double | Double |
| long | Long |
| boolean | Boolean |
除了Integer和Character定义的名称和对应的基本类型差异大,其他六种都是将首字母大写

2.JAVA基本数据类型和包装类相互转换


<br> 把基本数据类型 → 包装类:通过对应包装类的构造方法实现
<br> 除了Character外,其他包装类都可以传入一个字符串参数构建包装类对象
<br> 包装类 → 基本数据类型,包装类的实例方法xxxValue();    // xxx表示包装类对应的基本数据类型
<br> 代码:
<br> boolean bool = false;
<br> Boolean b2 = new Boolean(bool);
<br> Integer i = new Integer(3);
<br> int i2 = i.intValue();
<br> Boolean b1 = new Boolean("TRue");  //true
<br> boolean b2 = b1.booleanValue();
<br> Float f = new Float("3.14");   //3.14
<br> Integer i2 = new Integer("123s");  //NumberFormatException
<br> ```
<br> **基本类型和String之间的转换**
<br> String → 基本类型,除了Character外所有的包装类提供parseXxx(String s)静态方法,
<br> 用于把一个特定的字符串转换成基本类型变量;
<br> 基本类型 → String,String 类有静态方法valueOf(),用于将基本类型的变量转换成String类型
<br> 代码:
<br> ```
<br> String str = "66;
<br> int i = Integer.parseInt(str);     //String  --& 基本类型
<br> String s1 = String.valueOf(i);    //基本类型  --&  String
<br> ```

3.JAVA自动装箱与自动拆箱

什么是自动装箱?:可把一个基本类型变量直接赋给对应的包装类对象或则Object对象
什么是自动拆箱?:允许把包装类对象直接赋给对应的基本数据类型
代码:

Integer i = 3; //装箱
int i1 = i; //拆箱
Object flag = new Boolean(false);
if(flag instanceof Boolean){
Boolean b = (Boolean)flag;
boolean b2 = b;
}

4.JAVA Object类

什么是Object类
所有类的公共父类,一旦一个类没有显示地继承一个类则其直接父类一定是Object
一切数据类型都可用Object接收,class A extends Object{}等价于class A {}
代码:常见方法

public boolean equals(Object obj):对象比较
public int hashCode():取得该对象的Hash码
public String toString():对象描述


Object类的 toString()方法:“对象的描述”
笔者建议所有类都覆写此方法,直接打印输出对象时,会调用该对象的toString()方法
打印对象的时候,实际调用的对象实际指向的类的自我描述
全限定类名+@+十六进制的hashCode值,等价于 全限定类名+@+IntegertoHexString(该对象.hashCode);
equals也是判断是否指向同一个对象,没有实际意义,有必要可以重写

public boolean equals(Object obj) {}
String 覆写了 Object的equals方法:只比较字符的序列是否相同
==用于判断两个变量是否相等
基本类型:
引用类型:必须指向同一个对象,才true
只能比较有父子或平级关系的两个对象
new String("1") == new String("1"); ?

5.JAVA代码块

什么是代码块
代码块指的是使用"{}"括起来的一段代码,根据代码块存在的位置可以分为4种:
(1)普通代码块; (2)构造代码块; (3)静态代码块; (4)线程同步代码块;
代码块里变量的作用域:只在自己所在区域(前后的{})内有效;

(1)普通代码块:普通代码块就是直接定义在方法或语句中定义的代码块
代码:

.....main.....{
{
int x = 1;
System.out.println("普通代码块" + x);
}
int x = 99;
System.out.println("代码块之外" + x);
}



(2)构造代码块:直接写在类中的代码块,优先于构造方法执行,每次实例化对象之前都会执行构造代码块
代码:

public class Demo1 {
System.out.println("我是构造代码块");
}
public Demo2(){
System.out.println("我是构造方法");
}
public static void main(String[] args) {
Demo1 d1 = new Demo1();
Demo2 d2 = new Demo2();
}
}



(3)静态代码块:使用static 修饰的构造代码块:优先于主方法执行,优先于构造代码块执行,不管有创建多少对象,静态代码块只执行一次,可用于给静态变量赋值;
代码:

public class Demo3 {
System.out.println("我是构造代码块");
}
public Demo()4{
System.out.println("我是构造方法");
}
static {
System.out.println("我是静态代码块");
}
public static void main(String[] args) {
System.out.println("Main");
new Demo3();
new Demo4();
}
}



(4)线程同步代码块:在后面文章中笔者将详细提到这个问题!

6.JAVA构造方法的私有化

有的时候我们为了避免外界创建某类的实例,就将某类的构造方法私有化,将它的构造方法用private修饰:
私有化后外界就再也不能创建实例了,那内部呢?
其实即使将某类的构造方法私有化起来,外界也是可以创建它的实例的,此时就需要用到反射技术
代码:

class A{
private A(){}
public void show(){
System.out.println("A");
}
}
public class Demo {
public static void main(String[] args) throws Exception{
Class<A& clz = A.class;
Constructor<A& c = clz.getDeclaredConstructor();
c.setAccessible(true);
A a = c.newInstance();
a.show();
}
}

7.JAVA抽象类(abstract)

什么是抽象类
(1).使用abstract关键字声明的类为抽象类
(2).很多具有相同特征和行为的对象可以抽象为一个类,很多具有相同特征和行为的类可以为一个抽象类
(3).抽象类规则
1.抽象类可以没有抽象方法,有抽象方法的类必须是抽象类
2.非抽象类继承抽象类必须实现所有有抽象方法
3.抽象类可以有方法实现和属性
4.抽象类不能被实例化
5.抽象类不能声明为final

6.抽象类可以有普通方法

抽象类的语法格式:

//声明一个抽象类
public abstract class Wonmen{
private String name;
public abstract void say();//抽象方法
}


JAVA语言中使用abstract class来定义抽象类代码如下

/**
*定义一个抽象类
**/
public abstract class Demo5{
private String name; //定义私有成员变量属性
private String address; //定义私有成员变量属性
private int number; //定义私有成员变量属性
//定义构造方法
public Demo5(String name, String address, int number){
this.name = name;
this.address = address;
this.number = number;
}
public double computePay(){
System.out.println("这是 computePay");
return 0.0;
}
public void mailCheck(){
System.out.println("这是 " + this.name+ " " + this.address);
}
//定义toString方法
public String toString(){
return name + " " + address + " " + number;
}
//取得getName方法
public String getName(){
return name;
}
//getAddress方法
public String getAddress(){
return address;
}
//取得getNumber方法
public int getNumber(){
return number;
}
//设置Address方法
public void setAddress(String newAddress){
address = newAddress;
}
}

该类是抽象类,但是它仍然有3个成员变量,7个成员方法和1个构造方法

抽象方法abstract关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体
抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号

public abstract class Demo6{
private String name;
private String address;
private int number;
public abstract double computePay();
//其余代码
}

声明抽象方法会造成以下两个结果:
● 如果一个类包含抽象方法,那么该类必须是抽象类
● 任何子类必须重写父类的抽象方法,或者声明自身为抽象类

8.JAVA接口(interface)

什么是JAVA接口?:
(1).接口是一组行为的规范,定义,没有实现
使用接口,可以让我们的程序更加利于变化
接口是面向对象编程体系中的思想精髓之一
面向对象设计法则:基本接口编程
在JAVA编程语言中是一个抽象类型,是抽象方法的集合
接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念
类描述对象的属性和方法。接口则包含类要实现的方法
接口无法被实例化,但是可以被实现
一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类

(2).JAVA接口的定义格式
代码:

接口实现:
interface 接口名称{ }
class Girl implements Hit{
//抽象方法;
public void cry(){
//方法体
}
}

(3).JAVA接口的使用规则
1.接口可以继承多个接口
2.一个类可以实现多个接口,实现多个接口用逗号隔开
3.抽象类实现接口可以不实现方法
4.接口中的所有方法的访问权限都是public
5.接口中定义的属性都是常量

(4).JAVA接口与类相似点
● 一个接口可以有多个方法
接口文件保存在 .java 结尾的文件中,文件名使用接口名
接口的字节码文件保存在 .class 结尾的文件中

(5).JAVA接口与类的区别
● 接口不能用于实例化对象
接口没有构造方法
接口中所有的方法必须是抽象方法
接口不能包含成员变量,除了 static 和 final 变量
接口不是被类继承了,而是要被类实现
接口支持多重继承
● 接口相应的字节码文件必须在与包名称相匹配的目录结构中

(6).JAVA接口特性
接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)
接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误
接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法


(7).JAVA抽象类和接口的区别
● 1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法是不可行的
● 2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型
● 3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法
● 4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口

JAVA接口的实现
代码:

public class MammalInt implements Animal{
public void eat(){
System.out.println("Mammal eats");
}
public void travel(){
System.out.println("Mammal travels");
}
public int noOfLegs(){
return 0;
}
public static void main(String args[]){
MammalInt m = new MammalInt();
m.eat();
m.travel();
}
}

## 9.接口与抽象类

接口与抽象类相同点:
都位于继承的顶端,用于被其他实现或继承;
都不能实例化;
都包含抽象方法,其子类都必须覆写这些抽象方法;
接口与抽象类区别:
抽象类为部分方法提供实现,避免子类重复实现这些方法,提供代码重用性;接口只能包含抽象方法;
一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承)
二者的选用:
优先选用接口,尽量少用抽象类,需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;

| NO. | 比较 | 抽象类 | 接口 |
| :-------- | --------:| :------: | :------: |
| 1 | 关键字 | 使用abstract class 声明 | 使用interface声明 |
| 2 | 定义 | 包含抽象方法的类 | 抽象方法和全局常量的集合 |
| 3 | 组成 | 属性、方法、构造方法、抽象方法、常量 | 全局常量、抽象方法 |
| 4 | 权限 | 抽象方法的权限可以任意 | 只能是public权限 |
| 5 | 使用 | 通过extends关键字继承抽象类 | 通过implements关键字实现接口 |
| 6 | 局限 | 抽象类存在单继承局限 | 没有局限,一个子类可以实现多个接口 |
| 7 | 顺序 | 一个子类只能先继承抽象类再实现多个接口

| 8 | 设计模式 | 模板设计 | 工厂设计模式、代理设计模式 |
| 9 | 实际作用 | 只能做一个模板使用 | 作为标准、表现能力 |

| 10 | 使用 | 两者没有什么本质上的区别,但是从实际上来看,如果 一个程序中抽象类和接口都可以使用的话,则一定要优先考虑接口,因为接口可以避免单继承所带来的局限
| 11 | 实例化 | 都是依靠对象多态性,通过子类进行对象实例化 |

10.JAVA内部类

什么是内部类?:
内部类就是在类里面的类就是内部类,内部类就是一个在类的内部定义的类
类中有类:内部类:嵌套类或者是外部类:宿主类
把内部类隐藏在外部类之内,不许同包的其他类访问该类
内部类可以访问外部类的私有数据,外部类不能访问内部类的实现细节,比如字段;
观察编译后的字节码文件
非静态内部类;静态内部类,局部内部类,匿名内部类适合于仅使用一次使用的类

成员内部类格式

//声明一个类
class Outer{
//声明一个内部类
class Inner(){}
}

编译上述代码会产生两个文件 Outer.class和Outer$Inner.class

为什么要使用内部类内部类的作用
1.内部类可以很好的实现隐藏
一般的非内部类,是不允许有 private 与protected权限的,但内部类可以
2.内部类拥有外围类的所有元素的访问权限
3.可是实现多重继承
4.可以避免修改接口而实现同一个类中两种同名方法的调用


JAVA中的内部类共分为四种
静态内部类static inner class (also called nested class)
成员内部类member inner class
局部内部类local inner class
匿名内部类anonymous inner class


(1).JAVA非静态内部类
若外部类字段,内部类字段,内部类方法变量同名,则其访问方式分别是:
访问外部类的字段:外部类类名.this.字段
访问内部类字段:this.字段
访问内部类方法的局部变量:字段
代码:

//内部类访问字段方法
//声明一个类
public class Neibulei{
public static void main(String [] args){
new Snake().show();//调用内部类方法
}
}
//声明一个类
class Snake{
private String name = "外部类属性";//定义一个私有属性
//声明一个内部类
private class Node{
public String name = "内部类属性";
//定义一个方法
public void add2Tall(){
String name = "局部变量";
System.out.println("把"+name+"添加到尾巴");
System.out.println("把"+this.name+"添加到尾巴");
System.out.println("把"+Snake.this.name+"添加到尾巴");
}
}
//定义方法
public void show(){
new Node().add2Tall();//开辟内部类的方法
}
}



(2).外部类以外访问非静态内部类
内部类不能是private修饰,否则不能访问,外部类以外的地方定义内部类变量
非静态内部类对象是存放在外部类的对象里的,因此在创建非静态内部类对象之前,必须先创建其外部类的对象
代码:

//在外部类以外访问非静态内部类
//声明一个类
public class FangwenNeibu{
public static void main(String [] args){
Outer out = new Outer();//实例化外部对象,创建外部对象
Outer.Inner in = out.new Inner();//根据外部类对象创建内部类对象
in.show();//调用方法
}
}
//声明一个外部类
class Outer{
//声明一个内部类
class Inner{
//定义一个方法
public void show(){
System.out.println("非静态内部方法");
}
}
}


 
(3).静态内部类:
使用static修饰内部类,该内部类属于其外部类,而不属于外部类的实例;
静态内部类可包括静态成员也可包括非静态成员。根据静态成员不能访问非静态成员的规定,所以静态内部类不能访问外部类实例成员,只能访问外部类的静态成员;
代码:

//静态内部类
//声明一个类
public class JingTai{
public static void main(String [] args){
new Outer().test();//创建外部类对象并调用方法test
}
}
//声明一个外部类
class Outer{
private String name = "will";//声明一个私有属性并赋值给name
private static int age = 17;//声明一个私有静态整形常量布置给age
//定义一个静态内部类
static class StaticInner{
private String s = "ooxx";//定义一个私有的属性并把值赋值给s变量
private static int num = 13;//定义一个私有的属性并把值赋给整形num
//定义方法
public void show(){
//System.out.println(name);//不能访问
System.out.println(age);//可访问
System.out.println(new Outer().name);//开辟外部类并调用外部属性
}
}
//定义方法
public void test(){
//System.out.println(s);//访问不到
//System.out.println(num);//访问不到
System.out.println(StaticInner.num);//可以访问
System.out.println(new StaticInner().s);//可以访问
new StaticInner().show();//创建内部类对象并调用内部类方法show
}
}






(4).外部以访问静态类内部
代码:

//在外部以访问静态类内部
//声明一个类
public class WaiFangNei{
public static void main(String [] args){
Outer.StaticInner.staticShow();//调用静态内部类静态方法
new Outer.StaticInner().show();//调用静态内部类实例方法
}
}
//声明一个外部类
class Outer{
//声明一个静态内部类
static class StaticInner{
//定义一个show方法
public void show(){
System.out.println("静态内部类实例方法");//输出
}
//静态方法
public static void staticShow(){
System.out.println("静态内部类静态方法");//输出
   }
 }
 }





(5).局部内部类
局部内部类:定义在方法里的内部类;
特点:不能在宿主类以外的地方使用,局部内部类也不能使用访问修饰符和static修饰;
局部内部类只能访问方法中final修饰的局部变量:因为final修饰的变量相当于一个常量,其生命周期超出了方法运行的生命周期;
代码:

//局部内类
//声明一个类
public class JuBu{
String name = "will";//定义属性
//定义主方法
public static void main(String [] args){
new JuBu().show();
}
}
//声明一个方法
public void show(){
final int num = 10;//final修饰局部变量
//定义一个内部类
class localClass{
//定义方法
public void test(){
System.out.println(name+"--&"+num);
}
}
new localClass().test();//调用
}







(6).局部内部类
局部内部类:定义在方法里的内部类;
特点:不能在宿主类以外的地方使用,局部内部类也不能使用访问修饰符和static修饰;
局部内部类只能访问方法中final修饰的局部变量:因为final修饰的变量相当于一个常量,其生命周期超出了方法运行的生命周期;
适合只使用一次的类,不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建匿名内部类的对象
匿名内部类不能定义构造器,因为匿名内部类没有类名
匿名内部类格式

new 父类构造器([实参列表]) 或 接口(){
//匿名内部类的类体部分
}

注意:匿名内部类必须继承一个父类或者实现一个接口,但最多只能一个父类或实现一个接口;






(7).枚举类(enum)
什么是枚举?:
枚举就是要让各种类型的变量的取值只能为若干个固定值得一个
枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则编译器就会报错
枚举可以让编译器在编译时就控制源程序赋给的非法值,使用普通变量的方式在开发阶段无法实现这一目标
在JDK1.5之后,使用关键字enum定义一种新的类型,称为枚举类型
使用enum声明,默认直接继承了java.lang.Enum类,而不是Object类;
枚举类的对象是固定的,实例个数有限,枚举对象后可以跟()
枚举元素必须位于枚举类体中的最开始部分,枚举元素后要有分号与其他成员分隔
枚举类的构造方法的权限修饰符默认是private
一旦枚举对象后面加上{},那么该对象实际是枚举匿名内部类对象;
所有枚举类都提供一个静态的values()方法(返回该枚举类所有对象组成的数组),便于遍历所有枚举对象;
所有枚举类都提供一个静态的valueOf(String name)方法, 返回枚举类中对象名等于 name的对象
Enum是一个抽象类,是所有枚举类的直接父类;
Enum常见方法:

String name(); // 返回枚举实例名称;
int ordinal(); // 返回枚举实例在枚举类中的索引,从0开始;
String toString(); // 返回枚举对象的"自我描述";

在switch语句中使用枚举对象;
在枚举类中使用toString方法;
使用for-each中操作枚举对象;
枚举类的构造方法;
枚举类覆写接口抽象方法的两种方式;注意:匿名内部类,枚举实现单例模式;
代码:

//枚举类
//声明一个类
public class Meiju{
//定义主方法
public static void main(String [] args){
RnumDemo rnON = RnumDemo.ON;
System.out.println(rnON);
}
}
//声明一个枚举类
enum RnumDemo{
ON,OFF;
}



(8).枚举类的构造方法

enum Colors {
RED("红"),GREEN("绿"),BLUE("蓝");
private String name;
private Color(String name){
this.name = name;
}
public String getName(){
return name;
}
public String toString() {
return this.name;//this表示谁 ?
}
}

11.JAVA异常及异常处理机制

什么是异常?:
在程序中异常是阻止当前方法或作用域继续执行的问题,在程序中导致程序中断运行的一些指令
通俗的说,异常就是程序在运行时出现的不正常情况;
编写的程序不可能一帆风顺,若异常产生,却没进行正确的处理。则可能导致程序的中断,造成损失,所以我们在开发中要考虑到各种异常的发生,并对其作出正确的处理,确保程序的正常执行

JAVA异常体系
Throwable
Error
通常指JVM出现重大问题如:运行的类不存在或者内存溢出
不需要编写针对代码对其处理,程序无法处理
Exception
在运行时运行出现的一些情况,可以通过try,catch,finally处理
Exception 和 Error的子类名大都是以父类名作为后缀
JAVA异常其实是对不正常情况的一种描述,并将其封装成对象
JAVA在 设计异常体系时,将容易出现的异常情况都封装成了对象


JAVA 内置异常类
JAVA语言定义了一些异常类在 java.lang 标准包中
标准运行时异常类的子类是最常见的异常类。由于 java.lang 包是默认加载到所有的 Java 程序的,所以大部分从运行时异常类继承而来的异常都可以直接使用,Java 根据各个类库也定义了一些其他的异常,下面的表中列出了 Java 的非检查性异常

| 异常 | 描述 |
| :-------- | --------:|
| ArithmeticException | 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例 |
| ArrayStoreException | 将错误类型的对象存储到一个对象数组时抛出的异常 |
| ArrayIndexOutOfBoundsException | 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引 |
| ClassCastException | 将对象强制转换为不是实例的子类时,抛出该异常 |
| IllegalMonitorStateException | 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程 |
| IllegalArgumentException | 抛出的异常表明向方法传递了一个不合法或不正确的参数 |
| IllegalStateException | 在非法或不适当的时间调用方法时产生的信号,换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下 |
| IllegalThreadStateException | 线程没有处于请求操作所要求的适当状态时抛出的异常 |
| IndexOutOfBoundsException | 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出 |
| NegativeArraySizeException | 应用程序创建大小为负的数组,则抛出该异常 |
| NullPointerException | 应用程序在需要对象的地方使用 null 时,抛出该异常 |
| NumberFormatException | 应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常 |
| SecurityException | 由安全管理器抛出的异常,指示存在安全侵犯 |
| StringIndexOutOfBoundsException | 异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小 |
| UnsupportedOperationException | 不支持请求的操作时,抛出该异常 |
| ClassNotFoundException | 应用程序试图加载类时,找不到相应的类,抛出该异常 |
| CloneNotSupportedException | 当调用Object类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常 |
| IllegalAccessException | 拒绝访问一个类的时,抛出该异常 |
| InstantiationException | 使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常 |
| InterruptedException | 一个线程被另一个线程中断,抛出该异常 |
| NoSuchFieldException | 请求的变量不存在 |
| NoSuchMethodException | 请求的方法不存在 |




演示有异常程序的代码

public class Demo7 {
public static void main(String[] args){
System.out.println("begin");
divide(17/0);
System.out.println("ending");
}
publc static void divide(int a,int b){
int c= a/b;
}
}

一旦出现异常,程序会立即终止


看完上面得异常程序,读者思考,将如何处理异常程序呢
异常处理过程分析
一旦产生异常,则系统会自动产生一个异常类的实例化对象
此时如果存在于try语句,则会自动找到匹配的catch语句执行
如果没有异常处理,则程序将退出,并由系统报告错误
所有的catch根据方法的参数匹配异常类的实例化对象,如果匹配成功,则表示由此catch进行处理
下面笔者将详细介绍JAVA处理异常的5个关键字
JAVA异常处理的5个关键字

try 与 catch
finally
throw 与 throws

捕获异常:先捕获小异常再捕获大异常
程序是调出来的,不是立马编写出来的;多测试是程序员的必修课之一


JAVA异常处理格式

try{
//可能出异常的代码
} catch(异常类型 对象){
//处理该异常类型的语句
}
finally {
//异常的统一出口
//一定会执行的代码
//catch块使用System.exit(1);除外
}

当try语句块出现异常,程序会自动跳到catch语句块去找匹配的异常类型,并执行异常处理语句,finally语句块是异常的统一出口,异常处理后,程序不会因为出现异常而退出


异常处理代码

//异常处理
//声明一个类
public class Yichang{
//方法
public static void main(String [] args){
int a = 10;//定义一个常量
int b = 0;//定义一个常量
int c = 0;
//把有可能发生异常的代码块段放到try块中,通过catch语句进行异常捕获
try{
c = a/b;
}catch(ArithmeticException ex){
System.out.println("算数运算异常");
}
System.out.println(c);
}
}







Throwable中的方法
String getMessage(); 获取异常信息,返回字符串
String toString(); 获取异常类名和异常信息,返回字符串
void printStackTrace(); 打印异常在堆栈中的跟踪信息;
获取异常类名和异常信息,以及异常出现在程序中的位置
方便程序开发阶段的调试(一般要打开),JVM默认的异常处理机制;




JAVA多异常处理
声明异常时尽可能声明具体异常类型,方便更好的处理;
方法声明几个异常就对应有几个catch块;
若多个catch块中的异常出现继承关系,父类异常catch块放在最后;
在catch语句块使用Exception类作为异常类型时
所有子类实例都可以使用父类接收(向上转型),即所有的异常对象都可以使用Exception接收;
注:在java处理多异常时捕获小范围的异常必须放在大范围异常之前
JAVA多异常处理格式

try{
//可能出异常的代码
} catch(异常类A 对象){
//处理异常类型A的语句
}catch(异常类B 对象){
//处理异常类型B的语句
}.....
finally {
//一定会执行的代码
//catch块使用System.exit(1);除外
}

当try语句块出现异常,程序会自动跳到catch语句块去找匹配的异常类型,并执行异常处理语句,finally语句块是异常的统一出口,异常处理后,程序不会因为出现异常而退出




JAVA异常的分类
(1).编译时被检查异常; ---& Checked异常,在程序中必须使用try...catch处理
Checked异常特点:JAVA编译器会检查它,也就说程序中一旦出现这类异常,要么是没有try-catch语句捕获,或throws语句没有声明抛出它,编译就不会通过,也就说这种异常,程序要求必须处理

(2).编译时不被检测的异常; ---& Runtime异常,可以不使用try...catch处理,但一旦出现异常就将由JVM处理
Runtime异常特点:这种异常Java编译器不会检查它,也就说程序中出现这类异常的时候,即使不处理也没有问题,但是一旦出现异常,程序将异常终止,若采用异常处理,则会被相应的程序执行处理




throw关键字
自行抛出一个异常对象,抛出异常类的对象;若throw抛出的是Runtime异常:
程序可以显示使用try...catch来捕获并处理,也可以不管,直接交给方法调用者处理;若throw抛出Checked异常
要么放在try里自己处理,要么放在一个throws声明的方法里面,交给调用者处理




throws 与 throw关键字
throws用于在方法上声明该方法不需要处理的异常类型
throw用于抛出具体异常类的对象
throws与throw的区别
thorws用在方法上,后面跟异常类名,可以是多个异常类
throw用在方法内,后面跟异常对象,只能是一个


声明抛出一个 RemoteException 异常代码

如果一个方法没有捕获一个检查性异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。
也可以使用 throw 关键字抛出一个异常,无论它是新实例化的还是刚捕获到的。
import java.io.*;
public class className{
public void deposit(double amount) throws RemoteException{
throw new RemoteException();
}
}
一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。
例如,下面的方法声明抛出 RemoteException 和 InsufficientFundsException:
import java.io.*;
 public class className{
public void withdraw(double amount) throws RemoteException,
InsufficientFundsException
{
}





finally关键字
异常的统一出口:不管try块程序是否异常,也不管哪个catch执行,finally块总会执行
try语句块或会执行的catch语句块使用了JVM系统退出语句例外;//System.exit(1);
try块必须和 catch块或和finally同在,不能单独存在,二者必须出现一个
不要在finally中使用return 或throw语句,否则将会导致try、catch中的return或throw失效

初学(面向对象近阶段) Ⅲ 难点: ★★★★★★★

希望每一篇文章都能够对读者们提供帮助与提升,这乃是每一位笔者的初衷

感谢您的阅读 欢迎您的留言与建议

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号