Java內部類
內部類簡介
Java 一個類中可以嵌套另外一個類,語法格式如下:
class OuterClass { // 外部類
// ...
class NestedClass { // 嵌套類,或稱為內部類
// ...
}
}
嵌套類有如下幾種類型:
成員內部類
最簡單的一種內部類,形式如下,跟其他變數一樣,是一個類中的一個成員
class Outer {
String str = "hello";
public Outer(String str) {
this.str = str;
}
/* 內部類 */
class Inner {
public void showStr() {
System.out.println(str);
}
}
}
- 成員內部類可以無條件地訪問外部類的所有元素
- 外部類訪問內部類需要先創建一個內部類對象
- 成員內部類是依附外部類而存在
可以訪問外部類原理
編譯器會在編譯時生成外部類和內部類兩個位元組碼文件,還會給內部類的無參構造函數增加一個參數,為外部類的一個應用,且指向了外部類,故可以隨意使用外部類一切。
側面說明成員內部類依賴於外部類的優先創建,不然會初始化失敗
局部內部類
定義在一個方法或者一個作用域裡面的類,局部內部類的訪問僅限於方法內或者該作用域內
class MyClass{
public MyClass() {
}
}
class Outer{
public Outer(){
}
public MyClass getInner{
/* 局部內部類 */
class Inner extends MyClass{
int age = 0;
}
return new Inner();
}
}
局部內部類就像是方法裡面的一個局部變數一樣,是不能有 public、protected、private 以及 static 修飾符的
匿名內部類
先看一下官方給的例子
public class HelloWorldAnonymousClasses {
/**
* 包含兩個方法的HelloWorld介面
*/
interface HelloWorld {
public void greet();
public void greetSomeone(String someone);
}
public void sayHello() {
// 1、局部類EnglishGreeting實現了HelloWorld介面
class EnglishGreeting implements HelloWorld {
String name = "world";
public void greet() {
greetSomeone("world");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Hello " + name);
}
}
HelloWorld englishGreeting = new EnglishGreeting();
// 2、匿名類實現HelloWorld介面
HelloWorld frenchGreeting = new HelloWorld() {
String name = "tout le monde";
public void greet() {
greetSomeone("tout le monde");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Salut " + name);
}
};
// 3、匿名類實現HelloWorld介面
HelloWorld spanishGreeting = new HelloWorld() {
String name = "mundo";
public void greet() {
greetSomeone("mundo");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Hola, " + name);
}
};
englishGreeting.greet();
frenchGreeting.greetSomeone("Fred");
spanishGreeting.greet();
}
public static void main(String... args) {
HelloWorldAnonymousClasses myApp = new HelloWorldAnonymousClasses();
myApp.sayHello();
}
}
匿名類表達式包含以下內部分:
- 操作符:new;
- 一個要實現的介面或要繼承的類,案例一中的匿名類實現了HellowWorld介面,案例二中的匿名內部類繼承了Animal父類;
- 一對括弧,如果是匿名子類,與實例化普通類的語法類似,如果有構造參數,要帶上構造參數;如果是實現一個介面,只需要一對空括弧即可;
- 一段被”{}”括起來類聲明主體;
- 末尾的”;”號(因為匿名類的聲明是一個表達式,是語句的一部分,因此要以分號結尾)。
本部分參考JAVA匿名內部類(Anonymous Classes)
靜態內部類
靜態內部類是不需要依賴於外部類的,並且它不能使用外部類的非static成員變數或者方法,這個和普通靜態方法不能訪問非靜態方法或變數的原理一樣,具體可以了解一下類的載入生命周期。
簡單地說就是靜態變數或方法是屬於類的,非靜態方法或變數是屬於對象的,jvm載入類的時候就為類的靜態變數或方法分配記憶體的,而非靜態的需要等到要初始化對象時候才給分配記憶體,而這個過程是動態的,也就是等到我們什麼時候想用,才會有累的初始化過程。
簡單舉個例子:
class Outer {
int a = 1
static int a = 2;
public Outter() {
}
/* 靜態內部類 */
static class Inner {
public Inner() {
System.out.println(a); // 編譯會報錯
System.out.println(b);
}
}
}
使用:
public class Test {
public static void main(String[] args) {
Outer.Inner inner = new Outer.Inner();
}
}
內部類簡單應用
為什麼在 Java 中需要內部類?總結一下主要有以下四點內部類的使用場景和好處:
- 1.每個內部類都能獨立的繼承一個介面的實現,所以無論外部類是否已經繼承了某個(介面的)實現,對於內部類都沒有影響。內部類使得多繼承的解決方案變得完整。
- 2.方便將存在一定邏輯關係的類組織在一起,又可以對外界隱藏。
- 3.方便編寫事件驅動程式。
- 4.方便編寫執行緒程式碼。