java嵌套類: 靜態成員類、內部類
內部類: 非靜態成員類、匿名類、局部類
1. 靜態內部類
1.1 特點:可以訪問外圍類所有的靜態成員(屬性和方法)
1.2 特點:是外圍類的一個普通的靜態成員:比如用private修飾, 則只能在外圍類內部使用
1.3 功能:作爲內部類的輔助類來使用,例如構建器:舉個例子
public class Person {
private final String name;
private final int age;
private final double salary;
private Person(Builder builder) {
this.name = builder.name;
age = builder.age;
salary = builder.salary;
}
// 靜態內部類
public static class Builder {
private String name;
private int age;
private double salary;
public Builder name(String name) {
this.name = name;
return this;
}
public Builder age(int age) {
this.age = age;
return this;
}
public Builder salary(double salary) {
this.salary = salary;
return this;
}
public Person build() {
return new Person(this);
}
}
public static Builder builder() {
return new Builder();
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
}
// 測試類
public class Test {
public static void main(String[] args) {
System.out.println(Person.builder().name("zcs").age(10).salary(10.1).build());
}
}
// 打印結果
Person{name='zcs', age=10, salary=10.01}
2. 非靜態成員類
2.1 特點:非靜態成員類的每個實例都隱含地與一個外圍類的實例相關聯(涉及到的類在2.2)
OuterClass outerClass = new OuterClass();
OuterClass.NotStaticInnerClass notStaticInnerClass = outerClass.new NotStaticInnerClass();
2.2 特點:在非靜態成員類的實例方法內部,可以調用外圍實例上的方法(由2.1創建對象的過程就可以看出來,非靜態成員類持有了一個外圍類的引用,所以它可以調用外圍類的成員)
public class OuterClass {
public class NotStaticInnerClass {
private String name;
private int age;
public void name(String name) {
this.name = name;
}
public void inner() {
// 調用外圍類的方法
outer();
}
}
public void outer() {
System.out.println("outer method");
}
}
2.3 特點:利用修飾過的this構造獲得外圍實例的引用
public class OuterClass {
public class NotStaticInnerClass {
private String name;
private int age;
public void name(String name) {
this.name = name;
}
public void inner() {
// 內部類和外部類的成員名相同, 通過OuterClass.this獲取外圍類的引用
OuterClass.this.print();
}
public void print() {
System.out.println("inner print");
}
}
public void print() {
System.out.println("outer print");
}
}
注意事項: 如果聲明成員類不要求訪問外圍實例,就要始終把修飾符static放在它的聲明中!
原因:如果省略了static修飾符,則每個實例都將包含一個額外的指向外圍對象的引用,保存這份引用要消耗時間和空間,並且會導致外圍實例在符合垃圾回收時卻仍然得以保留, 由此造成的內存泄漏可能是災難性的 但是常常難以發現,因爲這個引用是不可見的
3. 匿名類: 一般用來創建小型函數對象, 但是一般都用lambda來代替了(因爲lambda表達式代碼更簡潔,可讀性更好)
舉個例子:如果有一個蘋果工廠, 我想挑選出紅色的蘋果放到另一個工廠,方法如下:
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class Apple {
private String color;
public static List<Apple> getSpecialApples(List<Apple> applesFactory, SelectAppleStrategy strategy) {
List<Apple> specialApplesFactory = new ArrayList<>();
for (Apple apple : applesFactory) {
if (strategy.selectApple(apple)) {
specialApplesFactory.add(apple);
}
}
return specialApplesFactory;
}
public static void main(String[] args) {
// 蘋果工廠
List<Apple> applesFactory = new ArrayList<>();
// 匿名內部類
getSpecialApples(applesFactory, new SelectAppleStrategy() {
@Override
public boolean selectApple(Apple apple) {
return "red".equalsIgnoreCase(apple.getColor());
}
});
// lambda表達式
getSpecialApples(applesFactory, apple -> "red".equalsIgnoreCase(apple.getColor()));
}
}
@FunctionalInterface
interface SelectAppleStrategy {
boolean selectApple(Apple apple);
}
4. 局部類: 略