關(guān)于java內(nèi)部類(lèi)的一些總結(jié)
匿名內(nèi)部類(lèi)了解一下?其實(shí)你每天都在用。
概念
將一個(gè)類(lèi)聲明在另一個(gè)類(lèi)的內(nèi)部,則將這個(gè)類(lèi)成為內(nèi)部類(lèi)。其與外部類(lèi)互相訪問(wèn)規(guī)則如下:
- 內(nèi)部類(lèi)可以訪問(wèn)外部類(lèi)的一切成員,包括私有成員;
- 外部類(lèi)若想訪問(wèn)內(nèi)部類(lèi)的成員,則必須聲明內(nèi)部類(lèi)的實(shí)例對(duì)象。
這個(gè)規(guī)則可以這么理解,外部類(lèi)和內(nèi)部類(lèi)就像父母和孩子:不管孩子要什么,父母總是會(huì)滿足;但孩子有獨(dú)立意識(shí)后,父母想了解孩子,就必須先得到孩子的同意才可以。
雖說(shuō)有了規(guī)則限制,但內(nèi)部類(lèi)又可以劃分為普通內(nèi)部類(lèi),靜態(tài)內(nèi)部類(lèi)以及匿名內(nèi)部類(lèi),因此在實(shí)際使用的時(shí)候,難免還是會(huì)有迷惑的地方。下面,用偽代碼進(jìn)行一下區(qū)別展示。
普通內(nèi)部類(lèi)的調(diào)用
class Outer{
private int value = 10;
class Inner{
private int value = 20;
void showValue(){
int value = 30;
System.out.print("this is funcValue -> " + value); //30
System.out.print("this is innerValue -> " + this.value); //20
System.out.print("this is outerValue -> " + Outer.this.value); //10
}
}
}
public class Test {
public static void main(String[] str) {
// 普通內(nèi)部類(lèi),實(shí)例化內(nèi)部類(lèi)對(duì)象時(shí),需要先實(shí)例化Outer類(lèi)對(duì)象,然后用Outer類(lèi)對(duì)象實(shí)例化Inner類(lèi)對(duì)象
Outer.Inner inner = new Outer().new Inner();
inner.showValue();
}
}
靜態(tài)內(nèi)部類(lèi)的調(diào)用
當(dāng)一個(gè)類(lèi)為內(nèi)部成員時(shí),其便可以像其他內(nèi)部屬性、方法一樣,被各種成員修飾符所修飾。
靜態(tài)內(nèi)部類(lèi)有兩個(gè)需要注意的點(diǎn):
- 因?yàn)楸宦暶鳛殪o態(tài),所以只能訪問(wèn)外部類(lèi)中同樣的靜態(tài)屬性、方法等;
- 當(dāng)一個(gè)類(lèi)為靜態(tài)內(nèi)部類(lèi)時(shí),外部類(lèi)對(duì)其的調(diào)用方式也會(huì)發(fā)生不同
class Outer{
private static int outStaticValue = 10;
private int outValue = 11;
static class Inner{
void showValue(){
System.out.print("this is static Inner " + outStaticValue); // 可以訪問(wèn)
System.out.print("this is static Inner " + outValue); // 編譯不通過(guò)
}
}
}
public class Test {
public static void main(String[] str) {
// 靜態(tài)內(nèi)部類(lèi),實(shí)例化靜態(tài)內(nèi)部類(lèi)對(duì)象時(shí),直接通過(guò)Outer.Inner獲取內(nèi)部類(lèi)即可
Outer.Inner inner = new Outer.Inner();
inner.showValue();
}
}
匿名內(nèi)部類(lèi)的調(diào)用
我們都熟悉匿名對(duì)象的用法,最簡(jiǎn)單的如 new Object().toString(),便是匿名對(duì)象的基本使用了。
同理,匿名內(nèi)部類(lèi)也是類(lèi)似的。
但是也有不同,那就是聲明匿名內(nèi)部類(lèi),要求類(lèi)必須繼承一個(gè)抽象類(lèi)或者實(shí)現(xiàn)一個(gè)接口。
下面看一下正常邏輯實(shí)現(xiàn),以及匿名內(nèi)部類(lèi)實(shí)現(xiàn)的代碼示例。
- 正常邏輯實(shí)現(xiàn)調(diào)用
abstract class ParentClass{
abstract void show();
}
class Outer{
class Inner extends ParentClass{
@Override
void show() {}
}
void func(){
new Inner().show();
}
}
public class Test {
public static void main(String[] str) {
// 正常邏輯實(shí)現(xiàn)調(diào)用
new Outer().func();
}
}
- 匿名內(nèi)部類(lèi)實(shí)現(xiàn)方式
abstract class ParentClass{
abstract void show();
}
class Outer{
void func(){
new ParentClass(){
@override
void show() {}
};
}
}
public class Test {
public static void main(String[] str) {
new Outer().func();
}
}
其實(shí)匿名內(nèi)部類(lèi)很簡(jiǎn)單,說(shuō)到底就是new Parent(){實(shí)現(xiàn)父類(lèi)或者接口的抽象方法}
是不是覺(jué)得很眼熟?沒(méi)錯(cuò),我們基本上每天都在用:
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {}
});
View.OnClickListener是一個(gè)抽象接口,我們這種實(shí)現(xiàn)方式,其實(shí)就是匿名內(nèi)部類(lèi)的實(shí)現(xiàn)。
定義在方法中的內(nèi)部類(lèi)
除了以上三種常見(jiàn)的形態(tài),內(nèi)部類(lèi)還可以聲明在局部,比如方法體內(nèi)部:
class Outer{
void show(){
class InnerFunc(){
void showMsg(){}
}
new InnerFunc().showMsg();
}
}
public class Test {
public static void main(String[] str) {
new Outer().show(); // 這樣就可以調(diào)用定義在方法內(nèi)部的類(lèi)了
}
}
但是這種形式在日常開(kāi)發(fā)中使用并不多,至少我沒(méi)有用過(guò)。說(shuō)到這里,感覺(jué)這個(gè)有點(diǎn)類(lèi)似于python的在方法中聲明方法:
def outerFunc():
def innerFunc():
return "this is innerFunc"
return innerFunc
內(nèi)部類(lèi)總結(jié)大概就要結(jié)束啦,以后想到再補(bǔ)充。
以上。