第7篇-JAVA面向?qū)ο螈?/h1>

2022-03-11 11:31 更新
  • 每篇一句 :任何值得去的地方,都沒(méi)有捷徑
  • 初學(xué)心得: 溫故而知新
  • (筆者:JEEP/711)[JAVA筆記 | 時(shí)間:2017-04-09| JAVA面向?qū)ο?Ⅲ]

目錄導(dǎo)航

[TOC]

1.JAVA基本包裝類型


| 基本數(shù)據(jù)類型 | 包裝類 |
| :-------- | --------: |
| byte | Byte |
| short | Short |
| int | Integer |
| char | Character |
| float | Float |
| double | Double |
| long | Long |
| boolean | Boolean |
除了Integer和Character定義的名稱和對(duì)應(yīng)的基本類型差異大,其他六種都是將首字母大寫(xiě)

2.JAVA基本數(shù)據(jù)類型和包裝類相互轉(zhuǎn)換


<br> 把基本數(shù)據(jù)類型 → 包裝類:通過(guò)對(duì)應(yīng)包裝類的構(gòu)造方法實(shí)現(xiàn)
<br> 除了Character外,其他包裝類都可以傳入一個(gè)字符串參數(shù)構(gòu)建包裝類對(duì)象
<br> 包裝類 → 基本數(shù)據(jù)類型,包裝類的實(shí)例方法xxxValue();    // xxx表示包裝類對(duì)應(yīng)的基本數(shù)據(jù)類型
<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之間的轉(zhuǎn)換**
<br> String → 基本類型,除了Character外所有的包裝類提供parseXxx(String s)靜態(tài)方法,
<br> 用于把一個(gè)特定的字符串轉(zhuǎn)換成基本類型變量;
<br> 基本類型 → String,String 類有靜態(tài)方法valueOf(),用于將基本類型的變量轉(zhuǎn)換成String類型
<br> 代碼:
<br> ```
<br> String str = "66;
<br> int i = Integer.parseInt(str);     //String  --& 基本類型
<br> String s1 = String.valueOf(i);    //基本類型  --&  String
<br> ```

3.JAVA自動(dòng)裝箱與自動(dòng)拆箱

什么是自動(dòng)裝箱?:可把一個(gè)基本類型變量直接賦給對(duì)應(yīng)的包裝類對(duì)象或則Object對(duì)象
什么是自動(dòng)拆箱?:允許把包裝類對(duì)象直接賦給對(duì)應(yīng)的基本數(shù)據(jù)類型
代碼:

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類
所有類的公共父類,一旦一個(gè)類沒(méi)有顯示地繼承一個(gè)類則其直接父類一定是Object
一切數(shù)據(jù)類型都可用Object接收,class A extends Object{}等價(jià)于class A {}
代碼:常見(jiàn)方法

public boolean equals(Object obj):對(duì)象比較
public int hashCode():取得該對(duì)象的Hash碼
public String toString():對(duì)象描述


Object類的 toString()方法:“對(duì)象的描述”
筆者建議所有類都覆寫(xiě)此方法,直接打印輸出對(duì)象時(shí),會(huì)調(diào)用該對(duì)象的toString()方法
打印對(duì)象的時(shí)候,實(shí)際調(diào)用的對(duì)象實(shí)際指向的類的自我描述
全限定類名+@+十六進(jìn)制的hashCode值,等價(jià)于 全限定類名+@+IntegertoHexString(該對(duì)象.hashCode);
equals也是判斷是否指向同一個(gè)對(duì)象,沒(méi)有實(shí)際意義,有必要可以重寫(xiě)

public boolean equals(Object obj) {}
String 覆寫(xiě)了 Object的equals方法:只比較字符的序列是否相同
==用于判斷兩個(gè)變量是否相等
基本類型:
引用類型:必須指向同一個(gè)對(duì)象,才true
只能比較有父子或平級(jí)關(guān)系的兩個(gè)對(duì)象
new String("1") == new String("1"); ?

5.JAVA代碼塊

什么是代碼塊?
代碼塊指的是使用"{}"括起來(lái)的一段代碼,根據(jù)代碼塊存在的位置可以分為4種:
(1)普通代碼塊; (2)構(gòu)造代碼塊; (3)靜態(tài)代碼塊; (4)線程同步代碼塊;
代碼塊里變量的作用域:只在自己所在區(qū)域(前后的{})內(nèi)有效;

(1)普通代碼塊:普通代碼塊就是直接定義在方法或語(yǔ)句中定義的代碼塊
代碼:

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



(2)構(gòu)造代碼塊:直接寫(xiě)在類中的代碼塊,優(yōu)先于構(gòu)造方法執(zhí)行,每次實(shí)例化對(duì)象之前都會(huì)執(zhí)行構(gòu)造代碼塊
代碼:

public class Demo1 {
System.out.println("我是構(gòu)造代碼塊");
}
public Demo2(){
System.out.println("我是構(gòu)造方法");
}
public static void main(String[] args) {
Demo1 d1 = new Demo1();
Demo2 d2 = new Demo2();
}
}



(3)靜態(tài)代碼塊:使用static 修飾的構(gòu)造代碼塊:優(yōu)先于主方法執(zhí)行,優(yōu)先于構(gòu)造代碼塊執(zhí)行,不管有創(chuàng)建多少對(duì)象,靜態(tài)代碼塊只執(zhí)行一次,可用于給靜態(tài)變量賦值;
代碼:

public class Demo3 {
System.out.println("我是構(gòu)造代碼塊");
}
public Demo()4{
System.out.println("我是構(gòu)造方法");
}
static {
System.out.println("我是靜態(tài)代碼塊");
}
public static void main(String[] args) {
System.out.println("Main");
new Demo3();
new Demo4();
}
}



(4)線程同步代碼塊:在后面文章中筆者將詳細(xì)提到這個(gè)問(wèn)題!

6.JAVA構(gòu)造方法的私有化

有的時(shí)候我們?yōu)榱吮苊馔饨鐒?chuàng)建某類的實(shí)例,就將某類的構(gòu)造方法私有化,將它的構(gòu)造方法用private修飾:
私有化后外界就再也不能創(chuàng)建實(shí)例了,那內(nèi)部呢?
其實(shí)即使將某類的構(gòu)造方法私有化起來(lái),外界也是可以創(chuàng)建它的實(shí)例的,此時(shí)就需要用到反射技術(shù)
代碼:

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關(guān)鍵字聲明的類為抽象類
(2).很多具有相同特征和行為的對(duì)象可以抽象為一個(gè)類,很多具有相同特征和行為的類可以為一個(gè)抽象類
(3).抽象類規(guī)則
1.抽象類可以沒(méi)有抽象方法,有抽象方法的類必須是抽象類
2.非抽象類繼承抽象類必須實(shí)現(xiàn)所有有抽象方法
3.抽象類可以有方法實(shí)現(xiàn)和屬性
4.抽象類不能被實(shí)例化
5.抽象類不能聲明為final

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

抽象類的語(yǔ)法格式:

//聲明一個(gè)抽象類
public abstract class Wonmen{
private String name;
public abstract void say();//抽象方法
}


JAVA語(yǔ)言中使用abstract class來(lái)定義抽象類代碼如下

/**
*定義一個(gè)抽象類
**/
public abstract class Demo5{
private String name; //定義私有成員變量屬性
private String address; //定義私有成員變量屬性
private int number; //定義私有成員變量屬性
//定義構(gòu)造方法
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;
}
//設(shè)置Address方法
public void setAddress(String newAddress){
address = newAddress;
}
}

該類是抽象類,但是它仍然有3個(gè)成員變量,7個(gè)成員方法和1個(gè)構(gòu)造方法

抽象方法abstract關(guān)鍵字同樣可以用來(lái)聲明抽象方法,抽象方法只包含一個(gè)方法名,而沒(méi)有方法體
抽象方法沒(méi)有定義,方法名后面直接跟一個(gè)分號(hào),而不是花括號(hào)

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

聲明抽象方法會(huì)造成以下兩個(gè)結(jié)果:
● 如果一個(gè)類包含抽象方法,那么該類必須是抽象類
● 任何子類必須重寫(xiě)父類的抽象方法,或者聲明自身為抽象類

8.JAVA接口(interface)

什么是JAVA接口?:
(1).接口是一組行為的規(guī)范,定義,沒(méi)有實(shí)現(xiàn)
使用接口,可以讓我們的程序更加利于變化
接口是面向?qū)ο缶幊腆w系中的思想精髓之一
面向?qū)ο笤O(shè)計(jì)法則:基本接口編程
在JAVA編程語(yǔ)言中是一個(gè)抽象類型,是抽象方法的集合
接口通常以interface來(lái)聲明。一個(gè)類通過(guò)繼承接口的方式,從而來(lái)繼承接口的抽象方法
接口并不是類,編寫(xiě)接口的方式和類很相似,但是它們屬于不同的概念
類描述對(duì)象的屬性和方法。接口則包含類要實(shí)現(xiàn)的方法
接口無(wú)法被實(shí)例化,但是可以被實(shí)現(xiàn)
一個(gè)實(shí)現(xiàn)接口的類,必須實(shí)現(xiàn)接口內(nèi)所描述的所有方法,否則就必須聲明為抽象類

(2).JAVA接口的定義格式
代碼:

接口實(shí)現(xiàn):
interface 接口名稱{ }
class Girl implements Hit{
//抽象方法;
public void cry(){
//方法體
}
}

(3).JAVA接口的使用規(guī)則
1.接口可以繼承多個(gè)接口
2.一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,實(shí)現(xiàn)多個(gè)接口用逗號(hào)隔開(kāi)
3.抽象類實(shí)現(xiàn)接口可以不實(shí)現(xiàn)方法
4.接口中的所有方法的訪問(wèn)權(quán)限都是public
5.接口中定義的屬性都是常量

(4).JAVA接口與類相似點(diǎn)
● 一個(gè)接口可以有多個(gè)方法
接口文件保存在 .java 結(jié)尾的文件中,文件名使用接口名
接口的字節(jié)碼文件保存在 .class 結(jié)尾的文件中

(5).JAVA接口與類的區(qū)別
● 接口不能用于實(shí)例化對(duì)象
接口沒(méi)有構(gòu)造方法
接口中所有的方法必須是抽象方法
接口不能包含成員變量,除了 static 和 final 變量
接口不是被類繼承了,而是要被類實(shí)現(xiàn)
接口支持多重繼承
● 接口相應(yīng)的字節(jié)碼文件必須在與包名稱相匹配的目錄結(jié)構(gòu)中

(6).JAVA接口特性
接口中每一個(gè)方法也是隱式抽象的,接口中的方法會(huì)被隱式的指定為 public abstract(只能是 public abstract,其他修飾符都會(huì)報(bào)錯(cuò))
接口中可以含有變量,但是接口中的變量會(huì)被隱式的指定為 public static final 變量(并且只能是 public,用 private 修飾會(huì)報(bào)編譯錯(cuò)誤
接口中的方法是不能在接口中實(shí)現(xiàn)的,只能由實(shí)現(xiàn)接口的類來(lái)實(shí)現(xiàn)接口中的方法


(7).JAVA抽象類和接口的區(qū)別
● 1. 抽象類中的方法可以有方法體,就是能實(shí)現(xiàn)方法的具體功能,但是接口中的方法是不可行的
● 2. 抽象類中的成員變量可以是各種類型的,而接口中的成員變量只能是 public static final 類型
● 3. 接口中不能含有靜態(tài)代碼塊以及靜態(tài)方法(用 static 修飾的方法),而抽象類是可以有靜態(tài)代碼塊和靜態(tài)方法
● 4. 一個(gè)類只能繼承一個(gè)抽象類,而一個(gè)類卻可以實(shí)現(xiàn)多個(gè)接口

JAVA接口的實(shí)現(xiàn)
代碼:

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.接口與抽象類

接口與抽象類相同點(diǎn):
都位于繼承的頂端,用于被其他實(shí)現(xiàn)或繼承;
都不能實(shí)例化;
都包含抽象方法,其子類都必須覆寫(xiě)這些抽象方法;
接口與抽象類區(qū)別:
抽象類為部分方法提供實(shí)現(xiàn),避免子類重復(fù)實(shí)現(xiàn)這些方法,提供代碼重用性;接口只能包含抽象方法;
一個(gè)類只能繼承一個(gè)直接父類(可能是抽象類),卻可以實(shí)現(xiàn)多個(gè)接口;(接口彌補(bǔ)了Java的單繼承)
二者的選用:
優(yōu)先選用接口,盡量少用抽象類,需要定義子類的行為,又要為子類提供共性功能時(shí)才選用抽象類;

| NO. | 比較 | 抽象類 | 接口 |
| :-------- | --------:| :------: | :------: |
| 1 | 關(guān)鍵字 | 使用abstract class 聲明 | 使用interface聲明 |
| 2 | 定義 | 包含抽象方法的類 | 抽象方法和全局常量的集合 |
| 3 | 組成 | 屬性、方法、構(gòu)造方法、抽象方法、常量 | 全局常量、抽象方法 |
| 4 | 權(quán)限 | 抽象方法的權(quán)限可以任意 | 只能是public權(quán)限 |
| 5 | 使用 | 通過(guò)extends關(guān)鍵字繼承抽象類 | 通過(guò)implements關(guān)鍵字實(shí)現(xiàn)接口 |
| 6 | 局限 | 抽象類存在單繼承局限 | 沒(méi)有局限,一個(gè)子類可以實(shí)現(xiàn)多個(gè)接口 |
| 7 | 順序 | 一個(gè)子類只能先繼承抽象類再實(shí)現(xiàn)多個(gè)接口

| 8 | 設(shè)計(jì)模式 | 模板設(shè)計(jì) | 工廠設(shè)計(jì)模式、代理設(shè)計(jì)模式 |
| 9 | 實(shí)際作用 | 只能做一個(gè)模板使用 | 作為標(biāo)準(zhǔn)、表現(xiàn)能力 |

| 10 | 使用 | 兩者沒(méi)有什么本質(zhì)上的區(qū)別,但是從實(shí)際上來(lái)看,如果 一個(gè)程序中抽象類和接口都可以使用的話,則一定要優(yōu)先考慮接口,因?yàn)榻涌诳梢员苊鈫卫^承所帶來(lái)的局限
| 11 | 實(shí)例化 | 都是依靠對(duì)象多態(tài)性,通過(guò)子類進(jìn)行對(duì)象實(shí)例化 |

10.JAVA內(nèi)部類

什么是內(nèi)部類?:
內(nèi)部類就是在類里面的類就是內(nèi)部類,內(nèi)部類就是一個(gè)在類的內(nèi)部定義的類
類中有類:內(nèi)部類:嵌套類或者是外部類:宿主類
把內(nèi)部類隱藏在外部類之內(nèi),不許同包的其他類訪問(wèn)該類
內(nèi)部類可以訪問(wèn)外部類的私有數(shù)據(jù),外部類不能訪問(wèn)內(nèi)部類的實(shí)現(xiàn)細(xì)節(jié),比如字段;
觀察編譯后的字節(jié)碼文件
非靜態(tài)內(nèi)部類;靜態(tài)內(nèi)部類,局部?jī)?nèi)部類,匿名內(nèi)部類適合于僅使用一次使用的類

成員內(nèi)部類格式

//聲明一個(gè)類
class Outer{
//聲明一個(gè)內(nèi)部類
class Inner(){}
}

編譯上述代碼會(huì)產(chǎn)生兩個(gè)文件 Outer.class和Outer$Inner.class

為什么要使用內(nèi)部類?內(nèi)部類的作用?
1.內(nèi)部類可以很好的實(shí)現(xiàn)隱藏
一般的非內(nèi)部類,是不允許有 private 與protected權(quán)限的,但內(nèi)部類可以
2.內(nèi)部類擁有外圍類的所有元素的訪問(wèn)權(quán)限
3.可是實(shí)現(xiàn)多重繼承
4.可以避免修改接口而實(shí)現(xiàn)同一個(gè)類中兩種同名方法的調(diào)用


JAVA中的內(nèi)部類共分為四種
靜態(tài)內(nèi)部類static inner class (also called nested class)
成員內(nèi)部類member inner class
局部?jī)?nèi)部類local inner class
匿名內(nèi)部類anonymous inner class


(1).JAVA非靜態(tài)內(nèi)部類
若外部類字段,內(nèi)部類字段,內(nèi)部類方法變量同名,則其訪問(wèn)方式分別是:
訪問(wèn)外部類的字段:外部類類名.this.字段
訪問(wèn)內(nèi)部類字段:this.字段
訪問(wèn)內(nèi)部類方法的局部變量:字段
代碼:

//內(nèi)部類訪問(wèn)字段方法
//聲明一個(gè)類
public class Neibulei{
public static void main(String [] args){
new Snake().show();//調(diào)用內(nèi)部類方法
}
}
//聲明一個(gè)類
class Snake{
private String name = "外部類屬性";//定義一個(gè)私有屬性
//聲明一個(gè)內(nèi)部類
private class Node{
public String name = "內(nèi)部類屬性";
//定義一個(gè)方法
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();//開(kāi)辟內(nèi)部類的方法
}
}



(2).外部類以外訪問(wèn)非靜態(tài)內(nèi)部類
內(nèi)部類不能是private修飾,否則不能訪問(wèn),外部類以外的地方定義內(nèi)部類變量
非靜態(tài)內(nèi)部類對(duì)象是存放在外部類的對(duì)象里的,因此在創(chuàng)建非靜態(tài)內(nèi)部類對(duì)象之前,必須先創(chuàng)建其外部類的對(duì)象
代碼:

//在外部類以外訪問(wèn)非靜態(tài)內(nèi)部類
//聲明一個(gè)類
public class FangwenNeibu{
public static void main(String [] args){
Outer out = new Outer();//實(shí)例化外部對(duì)象,創(chuàng)建外部對(duì)象
Outer.Inner in = out.new Inner();//根據(jù)外部類對(duì)象創(chuàng)建內(nèi)部類對(duì)象
in.show();//調(diào)用方法
}
}
//聲明一個(gè)外部類
class Outer{
//聲明一個(gè)內(nèi)部類
class Inner{
//定義一個(gè)方法
public void show(){
System.out.println("非靜態(tài)內(nèi)部方法");
}
}
}


 
(3).靜態(tài)內(nèi)部類:
使用static修飾內(nèi)部類,該內(nèi)部類屬于其外部類,而不屬于外部類的實(shí)例;
靜態(tài)內(nèi)部類可包括靜態(tài)成員也可包括非靜態(tài)成員。根據(jù)靜態(tài)成員不能訪問(wèn)非靜態(tài)成員的規(guī)定,所以靜態(tài)內(nèi)部類不能訪問(wèn)外部類實(shí)例成員,只能訪問(wèn)外部類的靜態(tài)成員;
代碼:

//靜態(tài)內(nèi)部類
//聲明一個(gè)類
public class JingTai{
public static void main(String [] args){
new Outer().test();//創(chuàng)建外部類對(duì)象并調(diào)用方法test
}
}
//聲明一個(gè)外部類
class Outer{
private String name = "will";//聲明一個(gè)私有屬性并賦值給name
private static int age = 17;//聲明一個(gè)私有靜態(tài)整形常量布置給age
//定義一個(gè)靜態(tài)內(nèi)部類
static class StaticInner{
private String s = "ooxx";//定義一個(gè)私有的屬性并把值賦值給s變量
private static int num = 13;//定義一個(gè)私有的屬性并把值賦給整形num
//定義方法
public void show(){
//System.out.println(name);//不能訪問(wèn)
System.out.println(age);//可訪問(wèn)
System.out.println(new Outer().name);//開(kāi)辟外部類并調(diào)用外部屬性
}
}
//定義方法
public void test(){
//System.out.println(s);//訪問(wèn)不到
//System.out.println(num);//訪問(wèn)不到
System.out.println(StaticInner.num);//可以訪問(wèn)
System.out.println(new StaticInner().s);//可以訪問(wèn)
new StaticInner().show();//創(chuàng)建內(nèi)部類對(duì)象并調(diào)用內(nèi)部類方法show
}
}






(4).外部以訪問(wèn)靜態(tài)類內(nèi)部
代碼:

//在外部以訪問(wèn)靜態(tài)類內(nèi)部
//聲明一個(gè)類
public class WaiFangNei{
public static void main(String [] args){
Outer.StaticInner.staticShow();//調(diào)用靜態(tài)內(nèi)部類靜態(tài)方法
new Outer.StaticInner().show();//調(diào)用靜態(tài)內(nèi)部類實(shí)例方法
}
}
//聲明一個(gè)外部類
class Outer{
//聲明一個(gè)靜態(tài)內(nèi)部類
static class StaticInner{
//定義一個(gè)show方法
public void show(){
System.out.println("靜態(tài)內(nèi)部類實(shí)例方法");//輸出
}
//靜態(tài)方法
public static void staticShow(){
System.out.println("靜態(tài)內(nèi)部類靜態(tài)方法");//輸出
   }
 }
 }





(5).局部?jī)?nèi)部類
局部?jī)?nèi)部類:定義在方法里的內(nèi)部類;
特點(diǎn):不能在宿主類以外的地方使用,局部?jī)?nèi)部類也不能使用訪問(wèn)修飾符和static修飾;
局部?jī)?nèi)部類只能訪問(wèn)方法中final修飾的局部變量:因?yàn)閒inal修飾的變量相當(dāng)于一個(gè)常量,其生命周期超出了方法運(yùn)行的生命周期;
代碼:

//局部?jī)?nèi)類
//聲明一個(gè)類
public class JuBu{
String name = "will";//定義屬性
//定義主方法
public static void main(String [] args){
new JuBu().show();
}
}
//聲明一個(gè)方法
public void show(){
final int num = 10;//final修飾局部變量
//定義一個(gè)內(nèi)部類
class localClass{
//定義方法
public void test(){
System.out.println(name+"--&"+num);
}
}
new localClass().test();//調(diào)用
}







(6).局部?jī)?nèi)部類
局部?jī)?nèi)部類:定義在方法里的內(nèi)部類;
特點(diǎn):不能在宿主類以外的地方使用,局部?jī)?nèi)部類也不能使用訪問(wèn)修飾符和static修飾;
局部?jī)?nèi)部類只能訪問(wèn)方法中final修飾的局部變量:因?yàn)閒inal修飾的變量相當(dāng)于一個(gè)常量,其生命周期超出了方法運(yùn)行的生命周期;
適合只使用一次的類,不能是抽象類,因?yàn)橄到y(tǒng)在創(chuàng)建匿名內(nèi)部類的時(shí)候,會(huì)立即創(chuàng)建匿名內(nèi)部類的對(duì)象
匿名內(nèi)部類不能定義構(gòu)造器,因?yàn)槟涿麅?nèi)部類沒(méi)有類名
匿名內(nèi)部類格式

new 父類構(gòu)造器([實(shí)參列表]) 或 接口(){
//匿名內(nèi)部類的類體部分
}

注意:匿名內(nèi)部類必須繼承一個(gè)父類或者實(shí)現(xiàn)一個(gè)接口,但最多只能一個(gè)父類或?qū)崿F(xiàn)一個(gè)接口;






(7).枚舉類(enum)
什么是枚舉?:
枚舉就是要讓各種類型的變量的取值只能為若干個(gè)固定值得一個(gè)
枚舉就是要讓某個(gè)類型的變量的取值只能為若干個(gè)固定值中的一個(gè),否則編譯器就會(huì)報(bào)錯(cuò)
枚舉可以讓編譯器在編譯時(shí)就控制源程序賦給的非法值,使用普通變量的方式在開(kāi)發(fā)階段無(wú)法實(shí)現(xiàn)這一目標(biāo)
在JDK1.5之后,使用關(guān)鍵字enum定義一種新的類型,稱為枚舉類型
使用enum聲明,默認(rèn)直接繼承了java.lang.Enum類,而不是Object類;
枚舉類的對(duì)象是固定的,實(shí)例個(gè)數(shù)有限,枚舉對(duì)象后可以跟()
枚舉元素必須位于枚舉類體中的最開(kāi)始部分,枚舉元素后要有分號(hào)與其他成員分隔
枚舉類的構(gòu)造方法的權(quán)限修飾符默認(rèn)是private
一旦枚舉對(duì)象后面加上{},那么該對(duì)象實(shí)際是枚舉匿名內(nèi)部類對(duì)象;
所有枚舉類都提供一個(gè)靜態(tài)的values()方法(返回該枚舉類所有對(duì)象組成的數(shù)組),便于遍歷所有枚舉對(duì)象;
所有枚舉類都提供一個(gè)靜態(tài)的valueOf(String name)方法, 返回枚舉類中對(duì)象名等于 name的對(duì)象
Enum是一個(gè)抽象類,是所有枚舉類的直接父類;
Enum常見(jiàn)方法:

String name(); // 返回枚舉實(shí)例名稱;
int ordinal(); // 返回枚舉實(shí)例在枚舉類中的索引,從0開(kāi)始;
String toString(); // 返回枚舉對(duì)象的"自我描述";

在switch語(yǔ)句中使用枚舉對(duì)象;
在枚舉類中使用toString方法;
使用for-each中操作枚舉對(duì)象;
枚舉類的構(gòu)造方法;
枚舉類覆寫(xiě)接口抽象方法的兩種方式;注意:匿名內(nèi)部類,枚舉實(shí)現(xiàn)單例模式;
代碼:

//枚舉類
//聲明一個(gè)類
public class Meiju{
//定義主方法
public static void main(String [] args){
RnumDemo rnON = RnumDemo.ON;
System.out.println(rnON);
}
}
//聲明一個(gè)枚舉類
enum RnumDemo{
ON,OFF;
}



(8).枚舉類的構(gòu)造方法

enum Colors {
RED("紅"),GREEN("綠"),BLUE("藍(lán)");
private String name;
private Color(String name){
this.name = name;
}
public String getName(){
return name;
}
public String toString() {
return this.name;//this表示誰(shuí) ?
}
}

11.JAVA異常及異常處理機(jī)制

什么是異常?:
在程序中異常是阻止當(dāng)前方法或作用域繼續(xù)執(zhí)行的問(wèn)題,在程序中導(dǎo)致程序中斷運(yùn)行的一些指令
通俗的說(shuō),異常就是程序在運(yùn)行時(shí)出現(xiàn)的不正常情況;
編寫(xiě)的程序不可能一帆風(fēng)順,若異常產(chǎn)生,卻沒(méi)進(jìn)行正確的處理。則可能導(dǎo)致程序的中斷,造成損失,所以我們?cè)陂_(kāi)發(fā)中要考慮到各種異常的發(fā)生,并對(duì)其作出正確的處理,確保程序的正常執(zhí)行

JAVA異常體系
Throwable
Error
通常指JVM出現(xiàn)重大問(wèn)題如:運(yùn)行的類不存在或者內(nèi)存溢出
不需要編寫(xiě)針對(duì)代碼對(duì)其處理,程序無(wú)法處理
Exception
在運(yùn)行時(shí)運(yùn)行出現(xiàn)的一些情況,可以通過(guò)try,catch,finally處理
Exception 和 Error的子類名大都是以父類名作為后綴
JAVA異常其實(shí)是對(duì)不正常情況的一種描述,并將其封裝成對(duì)象
JAVA在 設(shè)計(jì)異常體系時(shí),將容易出現(xiàn)的異常情況都封裝成了對(duì)象


JAVA 內(nèi)置異常類
JAVA語(yǔ)言定義了一些異常類在 java.lang 標(biāo)準(zhǔn)包中
標(biāo)準(zhǔn)運(yùn)行時(shí)異常類的子類是最常見(jiàn)的異常類。由于 java.lang 包是默認(rèn)加載到所有的 Java 程序的,所以大部分從運(yùn)行時(shí)異常類繼承而來(lái)的異常都可以直接使用,Java 根據(jù)各個(gè)類庫(kù)也定義了一些其他的異常,下面的表中列出了 Java 的非檢查性異常

| 異常 | 描述 |
| :-------- | --------:|
| ArithmeticException | 當(dāng)出現(xiàn)異常的運(yùn)算條件時(shí),拋出此異常。例如,一個(gè)整數(shù)"除以零"時(shí),拋出此類的一個(gè)實(shí)例 |
| ArrayStoreException | 將錯(cuò)誤類型的對(duì)象存儲(chǔ)到一個(gè)對(duì)象數(shù)組時(shí)拋出的異常 |
| ArrayIndexOutOfBoundsException | 用非法索引訪問(wèn)數(shù)組時(shí)拋出的異常。如果索引為負(fù)或大于等于數(shù)組大小,則該索引為非法索引 |
| ClassCastException | 將對(duì)象強(qiáng)制轉(zhuǎn)換為不是實(shí)例的子類時(shí),拋出該異常 |
| IllegalMonitorStateException | 拋出的異常表明某一線程已經(jīng)試圖等待對(duì)象的監(jiān)視器,或者試圖通知其他正在等待對(duì)象的監(jiān)視器而本身沒(méi)有指定監(jiān)視器的線程 |
| IllegalArgumentException | 拋出的異常表明向方法傳遞了一個(gè)不合法或不正確的參數(shù) |
| IllegalStateException | 在非法或不適當(dāng)?shù)臅r(shí)間調(diào)用方法時(shí)產(chǎn)生的信號(hào),換句話說(shuō),即 Java 環(huán)境或 Java 應(yīng)用程序沒(méi)有處于請(qǐng)求操作所要求的適當(dāng)狀態(tài)下 |
| IllegalThreadStateException | 線程沒(méi)有處于請(qǐng)求操作所要求的適當(dāng)狀態(tài)時(shí)拋出的異常 |
| IndexOutOfBoundsException | 指示某排序索引(例如對(duì)數(shù)組、字符串或向量的排序)超出范圍時(shí)拋出 |
| NegativeArraySizeException | 應(yīng)用程序創(chuàng)建大小為負(fù)的數(shù)組,則拋出該異常 |
| NullPointerException | 應(yīng)用程序在需要對(duì)象的地方使用 null 時(shí),拋出該異常 |
| NumberFormatException | 應(yīng)用程序試圖將字符串轉(zhuǎn)換成一種數(shù)值類型,但該字符串不能轉(zhuǎn)換為適當(dāng)格式時(shí),拋出該異常 |
| SecurityException | 由安全管理器拋出的異常,指示存在安全侵犯 |
| StringIndexOutOfBoundsException | 異常由 String 方法拋出,指示索引或者為負(fù),或者超出字符串的大小 |
| UnsupportedOperationException | 不支持請(qǐng)求的操作時(shí),拋出該異常 |
| ClassNotFoundException | 應(yīng)用程序試圖加載類時(shí),找不到相應(yīng)的類,拋出該異常 |
| CloneNotSupportedException | 當(dāng)調(diào)用Object類中的 clone 方法克隆對(duì)象,但該對(duì)象的類無(wú)法實(shí)現(xiàn) Cloneable 接口時(shí),拋出該異常 |
| IllegalAccessException | 拒絕訪問(wèn)一個(gè)類的時(shí),拋出該異常 |
| InstantiationException | 使用 Class 類中的 newInstance 方法創(chuàng)建一個(gè)類的實(shí)例,而指定的類對(duì)象因?yàn)槭且粋€(gè)接口或是一個(gè)抽象類而無(wú)法實(shí)例化時(shí),拋出該異常 |
| InterruptedException | 一個(gè)線程被另一個(gè)線程中斷,拋出該異常 |
| NoSuchFieldException | 請(qǐng)求的變量不存在 |
| NoSuchMethodException | 請(qǐng)求的方法不存在 |




演示有異常程序的代碼

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;
}
}

一旦出現(xiàn)異常,程序會(huì)立即終止


看完上面得異常程序,讀者思考,將如何處理異常程序呢
異常處理過(guò)程分析
一旦產(chǎn)生異常,則系統(tǒng)會(huì)自動(dòng)產(chǎn)生一個(gè)異常類的實(shí)例化對(duì)象
此時(shí)如果存在于try語(yǔ)句,則會(huì)自動(dòng)找到匹配的catch語(yǔ)句執(zhí)行
如果沒(méi)有異常處理,則程序?qū)⑼顺?,并由系統(tǒng)報(bào)告錯(cuò)誤
所有的catch根據(jù)方法的參數(shù)匹配異常類的實(shí)例化對(duì)象,如果匹配成功,則表示由此catch進(jìn)行處理
下面筆者將詳細(xì)介紹JAVA處理異常的5個(gè)關(guān)鍵字
JAVA異常處理的5個(gè)關(guān)鍵字

try 與 catch
finally
throw 與 throws

捕獲異常:先捕獲小異常再捕獲大異常
程序是調(diào)出來(lái)的,不是立馬編寫(xiě)出來(lái)的;多測(cè)試是程序員的必修課之一


JAVA異常處理格式

try{
//可能出異常的代碼
} catch(異常類型 對(duì)象){
//處理該異常類型的語(yǔ)句
}
finally {
//異常的統(tǒng)一出口
//一定會(huì)執(zhí)行的代碼
//catch塊使用System.exit(1);除外
}

當(dāng)try語(yǔ)句塊出現(xiàn)異常,程序會(huì)自動(dòng)跳到catch語(yǔ)句塊去找匹配的異常類型,并執(zhí)行異常處理語(yǔ)句,finally語(yǔ)句塊是異常的統(tǒng)一出口,異常處理后,程序不會(huì)因?yàn)槌霈F(xiàn)異常而退出


異常處理代碼

//異常處理
//聲明一個(gè)類
public class Yichang{
//方法
public static void main(String [] args){
int a = 10;//定義一個(gè)常量
int b = 0;//定義一個(gè)常量
int c = 0;
//把有可能發(fā)生異常的代碼塊段放到try塊中,通過(guò)catch語(yǔ)句進(jìn)行異常捕獲
try{
c = a/b;
}catch(ArithmeticException ex){
System.out.println("算數(shù)運(yùn)算異常");
}
System.out.println(c);
}
}







Throwable中的方法
String getMessage(); 獲取異常信息,返回字符串
String toString(); 獲取異常類名和異常信息,返回字符串
void printStackTrace(); 打印異常在堆棧中的跟蹤信息;
獲取異常類名和異常信息,以及異常出現(xiàn)在程序中的位置
方便程序開(kāi)發(fā)階段的調(diào)試(一般要打開(kāi)),JVM默認(rèn)的異常處理機(jī)制;




JAVA多異常處理
聲明異常時(shí)盡可能聲明具體異常類型,方便更好的處理;
方法聲明幾個(gè)異常就對(duì)應(yīng)有幾個(gè)catch塊;
若多個(gè)catch塊中的異常出現(xiàn)繼承關(guān)系,父類異常catch塊放在最后;
在catch語(yǔ)句塊使用Exception類作為異常類型時(shí)
所有子類實(shí)例都可以使用父類接收(向上轉(zhuǎn)型),即所有的異常對(duì)象都可以使用Exception接收;
注:在java處理多異常時(shí)捕獲小范圍的異常必須放在大范圍異常之前
JAVA多異常處理格式

try{
//可能出異常的代碼
} catch(異常類A 對(duì)象){
//處理異常類型A的語(yǔ)句
}catch(異常類B 對(duì)象){
//處理異常類型B的語(yǔ)句
}.....
finally {
//一定會(huì)執(zhí)行的代碼
//catch塊使用System.exit(1);除外
}

當(dāng)try語(yǔ)句塊出現(xiàn)異常,程序會(huì)自動(dòng)跳到catch語(yǔ)句塊去找匹配的異常類型,并執(zhí)行異常處理語(yǔ)句,finally語(yǔ)句塊是異常的統(tǒng)一出口,異常處理后,程序不會(huì)因?yàn)槌霈F(xiàn)異常而退出




JAVA異常的分類
(1).編譯時(shí)被檢查異常; ---& Checked異常,在程序中必須使用try...catch處理
Checked異常特點(diǎn):JAVA編譯器會(huì)檢查它,也就說(shuō)程序中一旦出現(xiàn)這類異常,要么是沒(méi)有try-catch語(yǔ)句捕獲,或throws語(yǔ)句沒(méi)有聲明拋出它,編譯就不會(huì)通過(guò),也就說(shuō)這種異常,程序要求必須處理

(2).編譯時(shí)不被檢測(cè)的異常; ---& Runtime異常,可以不使用try...catch處理,但一旦出現(xiàn)異常就將由JVM處理
Runtime異常特點(diǎn):這種異常Java編譯器不會(huì)檢查它,也就說(shuō)程序中出現(xiàn)這類異常的時(shí)候,即使不處理也沒(méi)有問(wèn)題,但是一旦出現(xiàn)異常,程序?qū)惓=K止,若采用異常處理,則會(huì)被相應(yīng)的程序執(zhí)行處理




throw關(guān)鍵字
自行拋出一個(gè)異常對(duì)象,拋出異常類的對(duì)象;若throw拋出的是Runtime異常:
程序可以顯示使用try...catch來(lái)捕獲并處理,也可以不管,直接交給方法調(diào)用者處理;若throw拋出Checked異常
要么放在try里自己處理,要么放在一個(gè)throws聲明的方法里面,交給調(diào)用者處理




throws 與 throw關(guān)鍵字
throws用于在方法上聲明該方法不需要處理的異常類型
throw用于拋出具體異常類的對(duì)象
throws與throw的區(qū)別
thorws用在方法上,后面跟異常類名,可以是多個(gè)異常類
throw用在方法內(nèi),后面跟異常對(duì)象,只能是一個(gè)


聲明拋出一個(gè) RemoteException 異常代碼

如果一個(gè)方法沒(méi)有捕獲一個(gè)檢查性異常,那么該方法必須使用 throws 關(guān)鍵字來(lái)聲明。throws 關(guān)鍵字放在方法簽名的尾部。
也可以使用 throw 關(guān)鍵字拋出一個(gè)異常,無(wú)論它是新實(shí)例化的還是剛捕獲到的。
import java.io.*;
public class className{
public void deposit(double amount) throws RemoteException{
throw new RemoteException();
}
}
一個(gè)方法可以聲明拋出多個(gè)異常,多個(gè)異常之間用逗號(hào)隔開(kāi)。
例如,下面的方法聲明拋出 RemoteException 和 InsufficientFundsException:
import java.io.*;
 public class className{
public void withdraw(double amount) throws RemoteException,
InsufficientFundsException
{
}





finally關(guān)鍵字
異常的統(tǒng)一出口:不管try塊程序是否異常,也不管哪個(gè)catch執(zhí)行,finally塊總會(huì)執(zhí)行
try語(yǔ)句塊或會(huì)執(zhí)行的catch語(yǔ)句塊使用了JVM系統(tǒng)退出語(yǔ)句例外;//System.exit(1);
try塊必須和 catch塊或和finally同在,不能單獨(dú)存在,二者必須出現(xiàn)一個(gè)
不要在finally中使用return 或throw語(yǔ)句,否則將會(huì)導(dǎo)致try、catch中的return或throw失效

初學(xué)(面向?qū)ο蠼A段) Ⅲ 難點(diǎn): ★★★★★★★

希望每一篇文章都能夠?qū)ψx者們提供幫助與提升,這乃是每一位筆者的初衷

感謝您的閱讀 歡迎您的留言與建議

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)