內(nèi)部類分為四類:成員內(nèi)部類、局部(作用域)內(nèi)部類岂丘、匿名內(nèi)部類陵究、靜態(tài)內(nèi)部類。
內(nèi)部類大比拼
內(nèi)部類 | 成員內(nèi)部類 | 局部(作用域)內(nèi)部類 | 匿名內(nèi)部類 | 靜態(tài)內(nèi)部類 |
---|---|---|---|---|
訪問修飾符 | 有 | 無 | 無 | 有 |
成員內(nèi)部類
就像一個(gè)成員變量和方法一樣奥帘,你說她有沒有修飾符铜邮?有的呀!同時(shí)可以訪問外部類的靜態(tài)/非靜態(tài)變量和方法寨蹋。
若內(nèi)部類擁有與外部類同名成員(變量/方法)松蒜,默認(rèn)訪問成員內(nèi)部類。訪問外部 外部類.this.成員(變量/方法)
綜上:想成員一樣的成員內(nèi)部類钥庇,使用時(shí)需要先創(chuàng)建外部對(duì)象牍鞠。
public class Outter {
private Inner inner = null;
public void printMsg() {
System.out.println("我是一個(gè)快樂的外部類");
}
public class Inner {
public void printMsg() {
System.out.println("我是一個(gè)快樂的內(nèi)部類");
}
public void printAgain() {
this.printMsg();
Outter.this.printMsg();
}
}
/**
* 聽說使用getXXX的方式獲取實(shí)例對(duì)象會(huì)更優(yōu)雅哦
*/
public Inner getInner() {
if (null == inner)
inner = new Inner();
return inner;
}
public static void main (String[] args) {
//創(chuàng)建外部類對(duì)象
Outter outter = new Outter();
Outter.Inner inner = outter.new Inner();
Inner inner2 = outter.getInner();
inner.printMsg();
inner2.printMsg();
outter.printMsg();
inner.printAgain();
}
}
打印結(jié)果:這是我隨手寫的一個(gè)丑陋的內(nèi)部類。printAgain寫了在內(nèi)部類調(diào)用同名外部類成員的方式评姨。
局部?jī)?nèi)部類
聯(lián)想一下难述,局部?局部變量啥的吐句,作用域是局部的胁后。這里的局部?jī)?nèi)部類是指方法內(nèi)定義內(nèi)部類和作用域內(nèi)定義內(nèi)部類。她們的訪問權(quán)限僅限方法/作用域嗦枢。
她們有訪問修飾符嗎攀芯?你想想,你家方法內(nèi)部的變量寫訪問修飾符了嗎文虏?小傻瓜侣诺。
public class Outter {
private MemberInner inner = null;
public void printMsg() {
System.out.println("Outter.printMsg: 我是一個(gè)快樂的外部類");
}
/**
* 成員內(nèi)部類
*/
public class MemberInner {
public void printMsg() {
System.out.println("Inner.printMsg: 我是一個(gè)快樂的內(nèi)部類");
}
public void printAgain() {
//他自己
this.printMsg();
//他外面的
Outter.this.printMsg();
}
}
/**
* 聽說使用getXXX的方式獲取實(shí)例對(duì)象會(huì)更優(yōu)雅哦
*/
public MemberInner getInner() {
if (null == inner)
inner = new MemberInner();
return inner;
}
public MemberInner ordinaryMethod() {
/**
*局部?jī)?nèi)部類-方法內(nèi)
*/
class LocalInner extends MemberInner{
@Override
public void printMsg() {
System.out.println("LocalInner.printMsg: 人家才不是成員內(nèi)部類呢,我是一個(gè)可愛的方法內(nèi)局部?jī)?nèi)部類啊!");
}
}
return new LocalInner();
}
public void anotherOrdinaryMethod (Boolean isTrue) {
if (isTrue) {
/**
*局部?jī)?nèi)部類-作用域
*/
class AnotherLocalInner {
public void printMsg() {
System.out.println("AnotherLocalInner.printMsg: 我是一個(gè)可愛的作用域內(nèi)部類案蟹铩!");
}
}
this.printMsg();
printMsg();
new AnotherLocalInner().printMsg();
}
}
public static void main (String[] args) {
//創(chuàng)建外部類對(duì)象
Outter outter = new Outter();
//成員內(nèi)部類
Outter.MemberInner inner = outter.new MemberInner();
MemberInner inner2 = outter.getInner();
inner.printMsg();
inner2.printMsg();
outter.printMsg();
inner.printAgain();
System.out.println("----------------------華麗麗的分割線---------------------");
//局部?jī)?nèi)部類
outter.ordinaryMethod().printMsg();
outter.anotherOrdinaryMethod(true);
}
}
打印結(jié)果:
Inner.printMsg: 我是一個(gè)快樂的內(nèi)部類
Inner.printMsg: 我是一個(gè)快樂的內(nèi)部類
Outter.printMsg: 我是一個(gè)快樂的外部類
Inner.printMsg: 我是一個(gè)快樂的內(nèi)部類
Outter.printMsg: 我是一個(gè)快樂的外部類
----------------------華麗麗的分割線---------------------
LocalInner.printMsg: 人家才不是成員內(nèi)部類呢搔确,我是一個(gè)可愛的方法內(nèi)局部?jī)?nèi)部類啊灭忠!
Outter.printMsg: 我是一個(gè)快樂的外部類
Outter.printMsg: 我是一個(gè)快樂的外部類
AnotherLocalInner.printMsg: 我是一個(gè)可愛的作用域內(nèi)部類吧潘恪!
Process finished with exit code 0
綜上:無
匿名內(nèi)部類
感覺大多是用在swing編程弛作,監(jiān)聽事件啊涕蜂、接口回調(diào)什么的。對(duì)繼承方法的重寫或者實(shí)現(xiàn)什么的映琳。
她沒有訪問修飾符宇葱,由于沒有名字(類名)瘦真,可憐得連構(gòu)造方法也沒有QAQ(不能定義構(gòu)造方法,但有內(nèi)部代碼塊來初始化參數(shù))黍瞧。
public class Outter {
private MemberInner inner = null;
public void printMsg() {
System.out.println("Outter.printMsg: 我是一個(gè)快樂的外部類");
}
/**
* 成員內(nèi)部類
*/
public class MemberInner {
public void printMsg() {
System.out.println("Inner.printMsg: 我是一個(gè)快樂的內(nèi)部類");
}
public void printAgain() {
//他自己
this.printMsg();
//他外面的
Outter.this.printMsg();
}
}
/**
* 聽說使用getXXX的方式獲取實(shí)例對(duì)象會(huì)更優(yōu)雅哦
*/
public MemberInner getInner() {
if (null == inner)
inner = new MemberInner();
return inner;
}
/**
* 內(nèi)部類使用了方法的形參age
*/
public MemberInner ordinaryMethod(int age) {
/**
*局部?jī)?nèi)部類-方法內(nèi)
*/
class LocalInner extends MemberInner{
@Override
public void printMsg() {
System.out.println("倫家今年" + (age) + "歲呢");
System.out.println("LocalInner.printMsg: 人家才不是成員內(nèi)部類呢,我是一個(gè)可愛的方法內(nèi)局部?jī)?nèi)部類霸印印颤!");
}
}
return new LocalInner();
}
public void anotherOrdinaryMethod (Boolean isTrue) {
if (isTrue) {
/**
*局部?jī)?nèi)部類-作用域
*/
class AnotherLocalInner {
public void printMsg() {
System.out.println("AnotherLocalInner.printMsg: 我是一個(gè)可愛的作用域內(nèi)部類啊穿肄!");
}
}
this.printMsg();
printMsg();
new AnotherLocalInner().printMsg();
}
}
public void getAnonymousInner(AnonymousInner anonymousInner) {
System.out.println("這么可愛一定是" + anonymousInner.whatSex() + "吧年局!");
}
/**
* 內(nèi)部類使用方法形參
*/
public AnonymousInner transferValue(String sex) {
return new AnonymousInner() {
@Override
public String whatSex() {
return sex;
}
};
}
public static void main (String[] args) {
//創(chuàng)建外部類對(duì)象
Outter outter = new Outter();
//成員內(nèi)部類
Outter.MemberInner inner = outter.new MemberInner();
MemberInner inner2 = outter.getInner();
inner.printMsg();
inner2.printMsg();
outter.printMsg();
inner.printAgain();
System.out.println("----------------------華麗麗的分割線---------------------");
//局部?jī)?nèi)部類
outter.ordinaryMethod(12).printMsg();
outter.anotherOrdinaryMethod(true);
System.out.println("----------------------華麗麗的分割線---------------------");
//匿名內(nèi)部類
outter.getAnonymousInner(new AnonymousInner() {
@Override
public String whatSex() {
return "男孩子";
}
});
outter.getAnonymousInner(outter.transferValue("女孩子"));
}
}
/**
* 匿名內(nèi)部類的抽象類
*/
abstract class AnonymousInner {
public abstract String whatSex();
}
打印結(jié)果:
Inner.printMsg: 我是一個(gè)快樂的內(nèi)部類
Inner.printMsg: 我是一個(gè)快樂的內(nèi)部類
Outter.printMsg: 我是一個(gè)快樂的外部類
Inner.printMsg: 我是一個(gè)快樂的內(nèi)部類
Outter.printMsg: 我是一個(gè)快樂的外部類
----------------------華麗麗的分割線---------------------
倫家今年12歲呢
LocalInner.printMsg: 人家才不是成員內(nèi)部類呢,我是一個(gè)可愛的方法內(nèi)局部?jī)?nèi)部類跋滩矢否!
Outter.printMsg: 我是一個(gè)快樂的外部類
Outter.printMsg: 我是一個(gè)快樂的外部類
AnotherLocalInner.printMsg: 我是一個(gè)可愛的作用域內(nèi)部類啊脑溢!
----------------------華麗麗的分割線---------------------
這么可愛一定是男孩子吧僵朗!
這么可愛一定是女孩子吧!
在方法ordinaryMethod中屑彻,使用了外部方法的形參age验庙,在我試圖修改age時(shí),ide提示錯(cuò)誤:
Variable 'age' is accessed from within inner class,needs to be final or effectively final
變量age是在內(nèi)部類中訪問的社牲,需要時(shí)final修飾的或是實(shí)際上的最終變量粪薛。
在以前內(nèi)部類相關(guān)博文中提到,局部?jī)?nèi)部類和匿名內(nèi)部類使用外部類局部變量或形參時(shí)必須是final搏恤,但在JAVA8中不再必須final了违寿,是effectively final也支持。即只要你不去修改外部局部變量/形參的值熟空,則視為effectively final藤巢,就不會(huì)報(bào)錯(cuò)。
關(guān)于JAVA8以前必須使用final修飾的原因:
首先痛阻,一個(gè)有內(nèi)部類的類菌瘪,在編譯器編譯時(shí),會(huì)將內(nèi)部類單獨(dú)編譯成一個(gè)class文件阱当,即有兩個(gè)class文件俏扩。內(nèi)部類不是直接使用傳遞參數(shù),而是通過拷貝備份(利用自身構(gòu)造器)的方式來使用弊添,所以如果內(nèi)部類使用的變量和外部方法的變量不是同一個(gè)录淡,在內(nèi)部類中變量發(fā)生變化,會(huì)造成數(shù)據(jù)的不一致性油坝,因此用final來限定局部變量和形參的不可變嫉戚。
靜態(tài)內(nèi)部類
想一想刨裆,不充錢你會(huì)變得更強(qiáng)嗎?想一想彬檀,你在用你的工具類的時(shí)候需要去new她嗎帆啃?不。
所以窍帝,不需要外部類先去創(chuàng)建實(shí)例對(duì)象努潘。因此可以推斷,他(靜態(tài)內(nèi)部類)也不能使用外部類的非靜態(tài)成員(變量/方法)坤学,因?yàn)橥獠款惙庆o態(tài)成員是依賴具體對(duì)象的疯坤。
public class AnotherOutter {
public static class StaticInner {
public void printMsg() {
System.out.println("想一想,不充錢深浮?你會(huì)變得更強(qiáng)嗎压怠?----靜態(tài)內(nèi)部類");
}
}
public static void main (String[] args) {
StaticInner staticInner = new StaticInner();
staticInner.printMsg();
}
}
class Strangers {
public static void main (String[] args) {
AnotherOutter.StaticInner staticInner = new AnotherOutter.StaticInner();
staticInner.printMsg();
}
}
關(guān)于內(nèi)部類的總結(jié)就到這里了,如果有錯(cuò)誤的地方歡迎各位指正飞苇,謝謝(づ ̄3 ̄)づ╭?~菌瘫。。
作者:90后青壯年 (果女郎)
來源:CSDN
原文:https://blog.csdn.net/kiana168/article/details/83617481
版權(quán)聲明:本文為博主原創(chuàng)文章玄柠,轉(zhuǎn)載請(qǐng)附上博文鏈接突梦!