java內(nèi)部類(lèi)之成員內(nèi)部類(lèi)、局部?jī)?nèi)部類(lèi)和匿名內(nèi)部類(lèi)用法及說(shuō)明
內(nèi)部類(lèi)概念
一個(gè)類(lèi)中包含另外一個(gè)類(lèi)。
分類(lèi)
- 成員內(nèi)部類(lèi)。
- 局部?jī)?nèi)部類(lèi)(包含匿名內(nèi)部類(lèi))。
成員內(nèi)部類(lèi)
定義格式:
修飾符 class 類(lèi)名稱(chēng) {
修飾符 class 類(lèi)名稱(chēng) {
//...
}
//...
}
注意:
內(nèi)部類(lèi)使用外部,可以隨意訪問(wèn),但是外部類(lèi)使用內(nèi)部類(lèi)要借助內(nèi)部類(lèi)的對(duì)象。
使用成員內(nèi)部類(lèi)
兩種方法:
1. 間接方式:在外部類(lèi)的方法中,使用內(nèi)部類(lèi),然后main只調(diào)用外部類(lèi)的方法。
2. 直接方式:公式:
一般類(lèi):類(lèi)名稱(chēng) 對(duì)象名 = new 類(lèi)名稱(chēng)();
成員內(nèi)部類(lèi):外部?jī)?nèi)名稱(chēng).內(nèi)部類(lèi)名稱(chēng) 對(duì)象名 = new 外部類(lèi)名稱(chēng)().new 內(nèi)部類(lèi)名稱(chēng)();
Body.java含有一個(gè)內(nèi)部類(lèi)Heart
public class Body {
private String name;
//外部類(lèi)方法
public void methodBody() {
System.out.println("外部類(lèi)的方法");
new Heart().beat();//在外部類(lèi)方法中使用內(nèi)部類(lèi)。
}
public class Heart { //成員內(nèi)部類(lèi)
//內(nèi)部類(lèi)方法
public void beat() {
System.out.println("心臟跳動(dòng)");
System.out.println("我叫:"+name);
}
}
}下面分別介紹兩種方式訪問(wèn)內(nèi)部類(lèi):
間接方式訪問(wèn)內(nèi)部類(lèi)
Demo01InnerClass.java
public class Demo01InnerClass {
public static void main(String[] args) {
Body body = new Body();//外部類(lèi)對(duì)象
//通過(guò)外部類(lèi)的對(duì)象,調(diào)用外部類(lèi)的方法,里面間接使用內(nèi)部類(lèi)Heart
body.methodBody();直接方式訪問(wèn)內(nèi)部類(lèi)
public class Demo01InnerClass {
public static void main(String[] args) {
Body body = new Body();//外部類(lèi)對(duì)對(duì)象
//外部?jī)?nèi)名稱(chēng).內(nèi)部類(lèi)名稱(chēng) 對(duì)象名 = new 外部類(lèi)名稱(chēng)().new 內(nèi)部類(lèi)名稱(chēng)();
Body.Heart heart = new Body().new Heart();
heart.beat();
}
}外部類(lèi)和內(nèi)部類(lèi)變量重名問(wèn)題
當(dāng)外部類(lèi)的變量和內(nèi)部類(lèi)變量重名時(shí),在內(nèi)部類(lèi)方法中訪問(wèn)外部類(lèi)變量的格式是:外部類(lèi).this.外部類(lèi)成員變量名
public class Outer {
int number = 10;
public class Inner {
int number = 20;
public void methodInner() {
int number =30;//內(nèi)部類(lèi)方法的局部變量
System.out.println(number);//就近原則
System.out.println(this.number);
System.out.println(Outer.this.number);//外部類(lèi)的成員變量
}
}
}30
20
10
局部?jī)?nèi)部類(lèi)
如果類(lèi)是定義在一個(gè)方法內(nèi)部的,那么這就是一個(gè)局部?jī)?nèi)部類(lèi)。
“局部”:只有當(dāng)前所屬的方法才能使用它,出了這個(gè)方法外面就不能用了。
定義格式:
修飾符 class 外部類(lèi)名稱(chēng) {
修飾符 返回值類(lèi)型 外部類(lèi)方法名稱(chēng)(參數(shù)列表) {
class 局部?jī)?nèi)部類(lèi)名稱(chēng) {
//...
}
}
}Outer.java含有局部?jī)?nèi)部類(lèi)
public class Outer {
public void methodOuter() {
class Inner {
int num = 10;
public void methodInner() {
System.out.println(num);//10
}
}
//這個(gè)內(nèi)部列只有當(dāng)前所屬方法能夠訪問(wèn)這個(gè)類(lèi),出了這個(gè)方法就不能用了
Inner inner = new Inner();
inner.methodInner();
}
}DemoMain.java
public class DemoMain {
public static void main(String[] args) {
Outer outer = new Outer();
outer.methodOuter();
}
}結(jié)果:
10
注意:
局部?jī)?nèi)部類(lèi),如果希望訪問(wèn)所在方法的局部變量,那么這個(gè)局部變量必須是【有效final的】
備注:從java 8+開(kāi)始,只要局部變量事實(shí)不變,那么final關(guān)鍵字可以省略。
原因:
1. new 出來(lái)的對(duì)象在堆內(nèi)存當(dāng)中。
2. 局部變量是跟著方法走的,在棧內(nèi)存當(dāng)中。
3. 方法運(yùn)行結(jié)束后,立刻出棧,局部變量就會(huì)立刻消失。
4. 但是new出來(lái)的對(duì)象在堆當(dāng)中持續(xù)存在,直到垃圾回收消失。
public class MyOuter {
public void methodOuter() {
final int num = 10;//所在方法的局部變量
/*在棧中的局部變量可能隨著方法結(jié)束出棧消失了,但是創(chuàng)建的內(nèi)部類(lèi)對(duì)象還存在。
對(duì)象使用常量時(shí)能直接將常量copy進(jìn)來(lái),這時(shí)就要保證這個(gè)常量是不可更改的,也就是final。
*/
//num = 20;
class MyInner {
public void methodInner() {
System.out.println(num);
}
}
Inner myinner = new MyInner();
inner.methodInner();
}
}修飾內(nèi)部類(lèi)的權(quán)限
public > protected > (default) > private
定義一個(gè)類(lèi)的時(shí)候,權(quán)限修飾符規(guī)則:
- 外部類(lèi):public / (default)
- 成員內(nèi)部類(lèi):都可以寫(xiě),public > protected > (default) > private
- 局部?jī)?nèi)部類(lèi):什么都不能寫(xiě),但不是de
匿名內(nèi)部類(lèi)
如果接口的實(shí)現(xiàn)類(lèi)(或者是父類(lèi)的子類(lèi))只需要使用唯一的一次。
那么這種情況下就可以省略調(diào)該類(lèi)的定義,而改為使用【匿名內(nèi)部類(lèi)】。
匿名內(nèi)部類(lèi)定義格式:
接口名稱(chēng) 對(duì)象名 = new 類(lèi)名或者接口名稱(chēng)() {
//覆蓋重寫(xiě)所有抽象方法
};代表繼承了或者實(shí)現(xiàn)了該接口的子類(lèi)對(duì)象。
==接口MyInterface.java==
public interface MyInterface {
void method1();//抽象方法
void method2();
}==接口實(shí)現(xiàn)類(lèi)MyInterfaceImp.java==
public class MyInterfaceImpl implements MyInterface {
@Override
public void method1() {
System.out.println("實(shí)現(xiàn)類(lèi)覆蓋重寫(xiě)了方法1");
}
@Override
public void method2() {
System.out.println("實(shí)現(xiàn)了覆蓋重寫(xiě)方法2");
}
}測(cè)試類(lèi) 一
一般接口實(shí)現(xiàn)方法
DemoMain.java
public class DemoMain {
public static void main(String[] args) {
// MyInterface impl = new MyInterfaceImpl();
// impl.method();
}
}匿名內(nèi)部類(lèi)實(shí)現(xiàn)接口
DemoMain.java
public class DemoMain {
public static void main(String[] args) {
//使用匿名內(nèi)部類(lèi),但不匿名對(duì)象,對(duì)象名稱(chēng)就叫obj
MyInterface objA = new MyInterface() {
@Override
public void method1() {
System.out.println("匿名內(nèi)部類(lèi)實(shí)現(xiàn)了方法1-A");
}
@Override
public void method2() {
System.out.println("匿名內(nèi)部類(lèi)實(shí)現(xiàn)了方法2-A");
}
};
objA.method1();
objA.method2();
System.out.println("----------我是分割線----------");
//使用匿名內(nèi)部類(lèi),而且省略了對(duì)象名稱(chēng),也是匿名對(duì)象
new MyInterface() {
@Override
public void method1() {
System.out.println("匿名內(nèi)部類(lèi)實(shí)現(xiàn)了方法1-B");
}
@Override
public void method2() {
System.out.println("匿名內(nèi)部類(lèi)實(shí)現(xiàn)了方法2-B");
}
}.method1();
}
}結(jié)果:
匿名內(nèi)部類(lèi)實(shí)現(xiàn)了方法1-A
匿名內(nèi)部類(lèi)實(shí)現(xiàn)了方法2-A
----------我是分割線----------
匿名內(nèi)部類(lèi)實(shí)現(xiàn)了方法1-B
匿名內(nèi)部?jī)?nèi)應(yīng)用
實(shí)現(xiàn)倒計(jì)時(shí)5秒。
public class Demo02_Time {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("倒計(jì)時(shí)5秒");
}
},5000);//倒計(jì)時(shí)5秒
}
}注意事項(xiàng):
對(duì)格式進(jìn)行解析:"new 接口名稱(chēng) {...};"進(jìn)行解析
- new代表創(chuàng)建對(duì)象的動(dòng)作
- 接口名稱(chēng)就是匿名內(nèi)部類(lèi)需要實(shí)現(xiàn)那個(gè)接口
- {…}這才是匿名內(nèi)部類(lèi)的內(nèi)容
注意:
- 這個(gè)類(lèi)只需要使用一次。匿名內(nèi)部類(lèi)在創(chuàng)建對(duì)象時(shí),只能使用唯一一次。
- 如果希望多次希望多次創(chuàng)建對(duì)象,而且內(nèi)容一樣的話,那么就必須使用單獨(dú)定義的實(shí)現(xiàn)類(lèi)。
- 匿名對(duì)象,在調(diào)用的時(shí)候,只能調(diào)用唯一一次。
- 如果希望同一個(gè)對(duì)象,調(diào)用多次方法,那么必須給對(duì)象取一個(gè)名字。
- 匿名內(nèi)部類(lèi)是省略了【實(shí)現(xiàn)類(lèi)/子類(lèi)】,但是匿名對(duì)象是省略了【對(duì)象命名】。
強(qiáng)調(diào):匿名和匿名對(duì)象不是一回事。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
maven無(wú)法依賴(lài)spring-cloud-stater-zipkin的解決方案
這篇文章主要介紹了maven無(wú)法依賴(lài)spring-cloud-stater-zipkin如何解決,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05
IDEA設(shè)置字體隨鼠標(biāo)滾動(dòng)放大縮小的實(shí)現(xiàn)
這篇文章主要介紹了IDEA設(shè)置字體隨鼠標(biāo)滾動(dòng)放大縮小的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
JAVA使用SimpleDateFormat類(lèi)表示時(shí)間代碼實(shí)例
這篇文章主要介紹了JAVA使用SimpleDateFormat類(lèi)表示時(shí)間代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04
使用Java進(jìn)行Json數(shù)據(jù)的解析(對(duì)象數(shù)組的相互嵌套)
下面小編就為大家?guī)?lái)一篇使用Java進(jìn)行Json數(shù)據(jù)的解析(對(duì)象數(shù)組的相互嵌套)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08
Java應(yīng)用服務(wù)器之tomcat會(huì)話復(fù)制集群配置的示例詳解
這篇文章主要介紹了Java應(yīng)用服務(wù)器之tomcat會(huì)話復(fù)制集群配置的相關(guān)知識(shí),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07

