Java開發(fā)崗位面試被問到嵌套類怎么辦
嵌套類分類
- 靜態(tài)內部類(靜態(tài)嵌套類/靜態(tài)成員類/靜態(tài)類)
- 內部類(非靜態(tài)嵌套類)
內部成員類
本地內部類
匿名內部類
- 嵌套接口
靜態(tài)內部類
重要的結論:如果一個類被聲明為static(即static修飾class),只有一種情況,該類是靜態(tài)內部類。
1. 靜態(tài)內部類中能聲明哪些類,變量和方法?
沒有限制,可以聲明各種類型的類,變量,方法和靜態(tài)代碼塊,細分為:
類:
- 枚舉類
- 靜態(tài)內部類
- 內部類
- 接口
變量:
- 靜態(tài)變量
- 實例變量
方法:
- 靜態(tài)方法
- 實例方法
- 靜態(tài)代碼塊
2. 靜態(tài)內部類能訪問外圍類的哪些變量和方法?
靜態(tài)內部類可以訪問外圍類的任何成員,包括外圍類中聲明為private的成員,分為:
- 外圍類的靜態(tài)變量和方法(含私有):直接訪問
- 外圍類的實例變量和方法(含私有):通過外圍類的實例對象進行訪問
- 靜態(tài)內部類類似類的靜態(tài)變量,不需要依賴外圍類的實例對象而存在,可以看作是頂層類,可以直接通過外圍類來訪問。
3. 繼承方面
在繼承方面,靜態(tài)內部類與外圍類沒什么分別,在訪問權限允許的情況下:任何類都可以繼承靜態(tài)內部類,靜態(tài)內部類也可以繼承任何類(類沒有聲明為final)或實現(xiàn)任何接口。
public class OuterClass {
// 靜態(tài)變量
final static boolean FLAG_VALUE = true;
private static String name = "Outer Class";
// 實例變量
private int age;
// 靜態(tài)方法
private static String getName() {
return name;
}
// 實例方法
private void setAge(int age) {
this.age = age;
}
// 靜態(tài)內部類
public static class StaticInner {
// 聲明靜態(tài)變量
final static int x = 1;
static int y = 2;
// 聲明實例變量
int a;
// 聲明靜態(tài)代碼塊
static { }
// 聲明枚舉類
enum InnerEnum { }
// 聲明靜態(tài)內部類
static class Inner2 { }
// 聲明接口
interface Inner3 { }
// 聲明內部類
class Inner4 { }
// 聲明靜態(tài)方法
static void OperateStatic() {
System.out.println("靜態(tài)內部類直接訪問外圍類的靜態(tài)變量:name = " + name + ", FLAG_VALUE = " + FLAG_VALUE);
System.out.println("靜態(tài)內部類直接訪問外圍類的靜態(tài)方法:getName : " + getName());
// 靜態(tài)內部類不能直接訪問外圍類的實例變量和方法
//age = 30;
//setAge(30);
// 通過聲明外圍類對象,訪問外圍類對象的實例變量和方法
OuterClass outerClass = new OuterClass();
outerClass.age = 30;
outerClass.setAge(30);
}//加入Java開發(fā)交流君樣:756584822一起吹水聊天
// 聲明實例方法
void operate() {
System.out.println("靜態(tài)內部類直接訪問外圍類的靜態(tài)變量:name = " + name + ", FLAG_VALUE = " + FLAG_VALUE);
System.out.println("靜態(tài)內部類直接訪問外圍類的靜態(tài)方法:getName : " + getName());
// 靜態(tài)內部類不能直接訪問外圍類的實例變量和方法
//age = 30;
//setAge(30);
// 通過聲明外圍類對象,訪問外圍類對象的實例變量和方法
OuterClass outerClass = new OuterClass();
outerClass.age = 30;
outerClass.setAge(30);
}
}
}
內部類
1. 細分類
內部成員類
本地內部類(本地類/局部類)
匿名內部類(匿名類)
2. 內部類中能聲明哪些類,變量和方法?
內部類可以聲明實例變量,實例方法,final類型的靜態(tài)變量。
內部類不可以聲明靜態(tài)成員:包括靜態(tài)變量,靜態(tài)方法,靜態(tài)內部類,嵌套接口,靜態(tài)初始化塊。
細分為:
類:
- 只能聲明內部類
- 不能聲明枚舉類,靜態(tài)內部類,接口
變量:
- 只能聲明實例變量,final類型靜態(tài)變量
- 不能聲明靜態(tài)變量
方法:
- 只能聲明實例方法
- 不能聲明靜態(tài)方法
- 不能聲明靜態(tài)代碼塊
3. 內部類能訪問外圍類的哪些變量和方法?
沒有限制,外圍類的所有變量和方法(含私有)都可以直接訪問。
public class OuterClass {
// 靜態(tài)變量
final static boolean FLAG_VALUE = true;
private static String name = "Outer Class";
// 實例變量
private int age;
// 靜態(tài)方法
private static String getName() {
return name;
}
// 實例方法
private int getAge() {
return age;
}
// 內部類
public class Inner {
// 內部類不能聲明靜態(tài)變量
//private static String innerName = "Inner Class";
// 內部類只能聲明實例變量和final類型靜態(tài)變量
private int a;
final static int x = 1;
// 內部類不能聲明靜態(tài)代碼塊,枚舉類,靜態(tài)內部類,接口(枚舉類型和接口類型總是靜態(tài)的)
//static { }
//enum InnerEnum { }
//static class Inner2 { }
//interface Inner3 { }
// 內部類聲明內部類
class Inner4 { }
// 內部類不能聲明靜態(tài)方法
//static void OperateStatic() { }
// 內部類只能聲明實例方法
void operate() {
System.out.println("內部類訪問外圍類的靜態(tài)變量:name = " + name);
System.out.println("內部類訪問外圍類的靜態(tài)final變量:FLAG_VALUE = " + FLAG_VALUE);
System.out.println("內部類訪問外圍類的實例變量:age = " + (age = 40));
System.out.println("內部類訪問外圍類的靜態(tài)方法:getName() = " + getName());
System.out.println("內部類訪問外圍類的實例方法:getAge() = " + getAge());
}//加入Java開發(fā)交流君樣:756584822一起吹水聊天
}
}
4. 內部類是怎樣綁定外圍對象?
總結: 創(chuàng)建內部類對象(調用內部類的構造器)時,編譯器會隱式地在內部類中聲明一個final的外圍類類型的成員變量,然后將外圍類的對象,通過內部類的構造器傳遞給該final成員變量,用來將內部類對象綁定到外圍類對象。
public class Outer {
public class Inner {
// 編譯器自動隱式生成的外圍類類型的成員變量
final Outer this$0;
// 通過內部類構造器將外圍類的對象傳遞給this$0成員變量,實現(xiàn)內部類與外圍類對象的綁定
public Inner(Outer outer) {
this$0 = outer;
super();
}
}
}
創(chuàng)建內部類對象,如下:
Outer outer = new Outer(); Outer.Inner inner = outer.new Inner();
創(chuàng)建內部類對象時,系統(tǒng)會自動將外圍類的對象(outer)作為參數(shù)傳入內部類的構造器中,可認為是下面的方式:
Outer.Inner inner = outer.new Inner(outer);
5. 繼承方面
在訪問權限允許的情況下:內部類可以繼承任何類,也可以由任何類繼承。
問:那內部類與靜態(tài)內部類在繼承方面有什么區(qū)別呢?
答:內部類的對象總是要依賴于外部對象,因此一個類A繼承了一個內部類,則類A也必須要與內部類的外圍類對象相綁定,否則產生編譯錯誤。
1.反例:產生編譯錯誤
public class A extends Outer.Inner { }
class Outer {
class Inner { }
}
2.錯誤原因:想要創(chuàng)建A類對象,即A a = new A(); 會調用A類構造器,A類繼承內部類(Outer.Inner),則會調用內部類的構造器
這時沒有有效的外圍類對象,則無法實現(xiàn)內部類對象與外圍類對象的綁定,產生編譯錯誤。
3.修正
方法一:在A類構造器中傳遞一個外圍類的引用,通過外圍類對象來調用內部類的構造器,就相當于將外圍類的對象傳遞給了內部類的構造器,實現(xiàn)了內部類對象與外圍類對象的綁定。
public class A extends Outer.Inner {
public A(Outer outer) {
outer.super();
}
}
class Outer {
class Inner { }
}
方法二:外部類繼承外部類,內部類繼承內部類
public class A extends Outer {
class InnerA extends Outer.Inner { }
}
class Outer {
class Inner { }
}
創(chuàng)建A類的內部類InnerA對象:
A a = new A(); A.InnerA innerA = a.new InnerA();
創(chuàng)建內部類A.InnerA對象時,需要綁定外圍對象,a引用就是外圍類的對象,
內部類A.InnerA繼承了另外一個內部類Outer.Inner,在A.InnerA調用父類構造器時,也需要傳遞父類的外圍類(Outer)對象,
A類繼承了Outer類,因為子類的對像可以當作父類的對象來使用,因此a引用也是另一個內部類Outer.Inner的外圍對象。
6. 本地內部類
本地內部類:就是在方法,構造器,初始化塊中聲明的類。
本地內部類不是類的成員,從結構上類似一個局部變量,因此不能使用訪問修飾符(public,protected,private),也不能使用static修飾。
public class LocalInnerDemo {
private int x = 100;
// 1.本地內部類聲明在實例初始化塊中
{
class Local1 { }
}
// 2.本地內部類聲明在靜態(tài)初始化塊中
static {
class Local2 { }
}
// 3.本地內部類聲明在構造器中
public LocalInnerDemo() {
int y = 2;
final int z = 3;
class Local3 {
int a = x;
int b = y;
int c = z;
}
}//加入Java開發(fā)交流君樣:756584822一起吹水聊天
// 4.本地內部類聲明在實例方法中
public T1 method1() {
// 使用本地內部類實現(xiàn)某個接口,然后以接口形式返回
class Local4 implements T1 {
@Override
public void operate() {
System.out.println("Start to operate.");
}
}
return new Local4();
}
// 5.本地內部類聲明在靜態(tài)方法中
public static T1 method2() {
class Local5 implements T1 {
@Override
public void operate() {
System.out.println("Start to operate.");
}
}
return new Local5();
}
}
interface T1 {
void operate();
}
問:本地內部類聲明在實例環(huán)境(實例方法,構造器,實例初始化塊)和靜態(tài)環(huán)境中有什么區(qū)別呢?
答:實例環(huán)境:本地內部類需要與外圍類綁定,即會在類中隱式生成一個final的引用。
靜態(tài)環(huán)境:本地內部類不需要與外圍類綁定。
嵌套接口
嵌套接口:就是在類或者接口中聲明的接口。
- 不管聲明在類中,還是接口中,嵌套接口永遠都是靜態(tài)的。
- 當類實現(xiàn)了某個接口時,不需要實現(xiàn)嵌套接口的方法。
總結
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!
相關文章
Java實現(xiàn)數(shù)據(jù)脫敏(Desensitization)的操作指南
數(shù)據(jù)脫敏是指通過對敏感數(shù)據(jù)進行部分或完全隱藏處理,保護敏感信息在存儲和使用過程中的安全性,常見的應用場景包括日志記錄、接口返回、報表展示、數(shù)據(jù)分析等,本文給大家介紹了Java實現(xiàn)數(shù)據(jù)脫敏(Desensitization)的操作指南,需要的朋友可以參考下2025-02-02

