從屌絲到架構(gòu)師的飛越(面向?qū)ο笃?內(nèi)部類

一、介紹

面向?qū)ο蟪绦蛟O(shè)計(jì)中,可以在一個(gè)類的內(nèi)部定義另一個(gè)類。嵌套類分為兩種,即靜態(tài)嵌套類和非靜態(tài)嵌套類。靜態(tài)嵌套類使用很少,最重要的是非靜態(tài)嵌套類,也即是被稱作為內(nèi)部類(inner)。內(nèi)部類是JAVA語言的主要附加部分。內(nèi)部類幾乎可以處于一個(gè)類內(nèi)部任何位置,可以與實(shí)例變量處于同一級(jí),或處于方法之內(nèi),甚至是一個(gè)表達(dá)式的一部分。

內(nèi)部類的共性編輯

(1)內(nèi)部類仍然是一個(gè)獨(dú)立的類,在編譯之后內(nèi)部類會(huì)被編譯成獨(dú)立的.class文件,但是前面冠以外部類的類名和$符號(hào) 。

(2)內(nèi)部類不能用普通的方式訪問。內(nèi)部類是外部類的一個(gè)成員,因此內(nèi)部類可以自由地訪問外部類的成員變量,無論是否是private的 。

(3)內(nèi)部類聲明成靜態(tài)的,就不能隨便的訪問外部類的成員變量了,此時(shí)內(nèi)部類只能訪問外部類的靜態(tài)成員變量 。

二、知識(shí)點(diǎn)介紹

1、成員內(nèi)部類

2、局部?jī)?nèi)部類

3、靜態(tài)內(nèi)部類

4、匿名內(nèi)部類

三、上課對(duì)應(yīng)視頻的說明文檔

1、成員內(nèi)部類

成員內(nèi)部類是最普通的內(nèi)部類,它的定義為位于另一個(gè)類的內(nèi)部,形如下面的形式:

class Circle {

double radius = 0;

public Circle(double radius) {

this.radius = radius;

}

class Draw {? ? //內(nèi)部類

public void drawSahpe() {

System.out.println("drawshape");

}

}

}

這樣看起來,類Draw像是類Circle的一個(gè)成員,Circle稱為外部類。成員內(nèi)部類可以無條件訪問外部類的所有成員屬性和成員方法(包括private成員和靜態(tài)成員)。

class Circle {

private double radius = 0;

public static int count =1;

public Circle(double radius) {

this.radius = radius;

}

class Draw {? ? //內(nèi)部類

public void drawSahpe() {

System.out.println(radius);? //外部類的private成員

System.out.println(count);? //外部類的靜態(tài)成員

}

}

}

不過要注意的是,當(dāng)成員內(nèi)部類擁有和外部類同名的成員變量或者方法時(shí),會(huì)發(fā)生隱藏現(xiàn)象,即默認(rèn)情況下訪問的是成員內(nèi)部類的成員。如果要訪問外部類的同名成員,需要以下面的形式進(jìn)行訪問:

外部類.this.成員變量

外部類.this.成員方法

雖然成員內(nèi)部類可以無條件地訪問外部類的成員,而外部類想訪問成員內(nèi)部類的成員卻不是這么隨心所欲了。在外部類中如果要訪問成員內(nèi)部類的成員,必須先創(chuàng)建一個(gè)成員內(nèi)部類的對(duì)象,再通過指向這個(gè)對(duì)象的引用來訪問:

class Circle {

private double radius = 0;

public Circle(double radius) {

this.radius = radius;

getDrawInstance().drawSahpe();? //必須先創(chuàng)建成員內(nèi)部類的對(duì)象,再進(jìn)行訪問

}

private Draw getDrawInstance() {

return new Draw();

}

class Draw {? ? //內(nèi)部類

public void drawSahpe() {

System.out.println(radius);? //外部類的private成員

}

}

}

成員內(nèi)部類是依附外部類而存在的,也就是說,如果要?jiǎng)?chuàng)建成員內(nèi)部類的對(duì)象,前提是必須存在一個(gè)外部類的對(duì)象。創(chuàng)建成員內(nèi)部類對(duì)象的一般方式如下:

public class Test {

public static void main(String[] args)? {

//第一種方式:

Outter outter = new Outter();

Outter.Inner inner = outter.new Inner();? //必須通過Outter對(duì)象來創(chuàng)建

//第二種方式:

Outter.Inner inner1 = outter.getInnerInstance();

}

}

class Outter {

private Inner inner = null;

public Outter() {

}

public Inner getInnerInstance() {

if(inner == null)

inner = new Inner();

return inner;

}

//內(nèi)部類

class Inner {

public Inner() {

}

}

}

內(nèi)部類可以擁有private訪問權(quán)限、protected訪問權(quán)限、public訪問權(quán)限及包訪問權(quán)限。比如上面的例子,如果成員內(nèi)部類Inner用private修飾,則只能在外部類的內(nèi)部訪問,如果用public修飾,則任何地方都能訪問;如果用protected修飾,則只能在同一個(gè)包下或者繼承外部類的情況下訪問;如果是默認(rèn)訪問權(quán)限,則只能在同一個(gè)包下訪問。這一點(diǎn)和外部類有一點(diǎn)不一樣,外部類只能被public和包訪問兩種權(quán)限修飾。我個(gè)人是這么理解的,由于成員內(nèi)部類看起來像是外部類的一個(gè)成員,所以可以像類的成員一樣擁有多種權(quán)限修飾。

2、局部?jī)?nèi)部類

局部?jī)?nèi)部類是定義在一個(gè)方法或者一個(gè)作用域里面的類,它和成員內(nèi)部類的區(qū)別在于局部?jī)?nèi)部類的訪問僅限于方法內(nèi)或者該作用域內(nèi)。

class People{

public People() {

}

}

class Man{

public Man(){

}

public People getWoman(){

class Woman extends People{? //局部?jī)?nèi)部類

int age =0;

}

return new Woman();//返回局部?jī)?nèi)部類對(duì)象

}

}

注意,局部?jī)?nèi)部類就像是方法里面的一個(gè)局部變量一樣,是不能有public、protected、private以及static修飾符的。

3、靜態(tài)內(nèi)部類

靜態(tài)內(nèi)部類也是定義在另一個(gè)類里面的類,只不過在類的前面多了一個(gè)關(guān)鍵字static。靜態(tài)內(nèi)部類是不需要依賴于外部類的,這點(diǎn)和類的靜態(tài)成員屬性有點(diǎn)類似,并且它不能使用外部類的非static成員變量或者方法,這點(diǎn)很好理解,因?yàn)樵跊]有外部類的對(duì)象的情況下,可以創(chuàng)建靜態(tài)內(nèi)部類的對(duì)象,如果允許訪問外部類的非static成員就會(huì)產(chǎn)生矛盾,因?yàn)橥獠款惖姆莝tatic成員必須依附于具體的對(duì)象。

public class Test {

public static void main(String[] args)? {

//產(chǎn)生靜態(tài)內(nèi)部類對(duì)象

Outter.Inner inner = new Outter.Inner();

}

}

class Outter {

public Outter() {

}

//靜態(tài)內(nèi)部類

static class Inner {

public Inner() {

}

}

}

綜合案例:

public class Inner {

private int num = 3;

class Limian{

public void show(){

//內(nèi)部類可以訪問外部類的私有變量

System.out.println(num);

}

}

//局部?jī)?nèi)部類

public void method(){

int num2 = 44;

class JuIn{

public void zhanshi(){

/*

* 按理說局部?jī)?nèi)部類訪問局部變量,局部變量應(yīng)該用final修飾,但是不用final修飾也是可以訪問的,

* 這是因?yàn)樵贘DK8以下必須用final修飾,不然會(huì)報(bào)錯(cuò),

* Cannot refer to a non-final variable a inside an inner class defined in a different method,

* 但是在JDK8之后就不會(huì)出現(xiàn)這種狀況

* */

System.out.print(num2);

}

}

System.out.println("訪問局部變量"+num2);

//在局部創(chuàng)建內(nèi)部類對(duì)象

JuIn ji = new JuIn();

ji.zhanshi();

}

}

class StaticTest{

private static int num1 = 4;

//內(nèi)部類用靜態(tài)變量修飾

public static class Test{

public static void show(){

//靜態(tài)內(nèi)部類訪問外部變量必須用static修飾

System.out.println(num1);

}

}

}

class InnerDemo{

public static void main (String[] args){

//非靜態(tài)內(nèi)部類創(chuàng)建方法

Inner.Limian l = new Inner().new Limian();

l.show();

//靜態(tài)內(nèi)部類創(chuàng)建方式

StaticTest.Test t = new StaticTest.Test();

//調(diào)用方法一

t.show();

//調(diào)用方法二

StaticTest.Test.show();

//局部?jī)?nèi)部類的方法調(diào)用

Inner i = new Inner();

i.method();

}

}

4、內(nèi)部類的實(shí)際使用——匿名內(nèi)部類

(1)匿名內(nèi)部類概念

內(nèi)部類是為了應(yīng)對(duì)更為復(fù)雜的類間關(guān)系。我們?cè)谕瓿捎?jì)算機(jī)語言相對(duì)底層的位置才會(huì)涉及,日常業(yè)務(wù)中很難遇到,這里不做贅述。

最常用到的內(nèi)部類就是匿名內(nèi)部類,是局部?jī)?nèi)部類的一種。

匿名內(nèi)部類有兩個(gè)步驟:

a.臨時(shí)定義一個(gè)類型的子類

b.定義后即刻創(chuàng)建剛剛定義的這個(gè)類的對(duì)象

(2)匿名內(nèi)部類作用與格式

作用:匿名內(nèi)部類是創(chuàng)建某個(gè)類型子類對(duì)象的快捷方式。

格式:

new 父類或接口(){

//進(jìn)行方法重寫

};

代碼示例:

//已經(jīng)存在的父類:

public abstract class Person{

public abstract void eat();

}

//定義并創(chuàng)建該父類的子類對(duì)象,并用多態(tài)的方式賦值給父類引用變量

Person? p = new Person(){

public void eat() {

System.out.println(“我吃了”);

}

};

//調(diào)用eat方法

p.eat();

使用匿名對(duì)象的方式,將定義子類與創(chuàng)建子類對(duì)象兩個(gè)步驟由一個(gè)格式一次完成,。雖然是兩個(gè)步驟,但是兩個(gè)步驟是連在一起完成的。

匿名內(nèi)部類如果不定義變量引用,則也是匿名對(duì)象。代碼如下:

new Person(){

public void eat() {

System.out.println(“我吃了”);

}

}.eat();

/*

* 定義Fly接口

*/

public interface Fly {

public abstract void open();

public abstract void fly();

public abstract void close();

}

public class YanZi implements Fly{

@Override

public void open() {

System.out.println("張開小翅膀");

}

@Override

public void fly() {

System.out.println("能飛3000米高空");

}

@Override

public void close() {

System.out.println("關(guān)閉小翅膀,安全著陸");

}

//一個(gè)類中可以定義多個(gè)類,但只能有一個(gè)類public的

class Person()

}

}

/*

* 匿名內(nèi)部類

*

* new 父類/接口(){

*? //重寫需要重寫的方法

* };

*/

public class Test {

public static void main(String[] args) {

Fly yz = new YanZi();

yz.open();

yz.fly();

yz.close();

new YanZi().open();

System.out.println("-------------------");

//實(shí)現(xiàn)類對(duì)象賦值給父接口

Fly fj = new Fly(){

@Override

public void open() {

System.out.println("不需要張開翅膀,一直都是張開狀態(tài)");

}

@Override

public void fly() {

System.out.println("噴氣式助力飛行!");

}

@Override

public void close() {

System.out.println("不需要關(guān)閉翅膀,得哪撞哪");

}

};

fj.open();

fj.fly();

fj.close();

System.out.println("-----------------------------");

//實(shí)現(xiàn)類對(duì)象直接以匿名對(duì)象的方式調(diào)用方法

new Fly() {

@Override

public void open() {

System.out.println("小翅膀");

}

@Override

public void fly() {

System.out.println("亂飛");

}

@Override

public void close() {

System.out.println("各種撞樹");

}

}.fly();

}

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容