??內(nèi)部類就是一個類的內(nèi)部定義的類
一、成員內(nèi)部類
成員內(nèi)部類的格式如下:
class Outer{
class Inner{}
}
編譯上述代碼會產(chǎn)生兩個文件:
Outer.class 和 Outer$Inner.class
public class Test1 {
public static void main(String[] args){
Outer outer = new Outer();
// 在外部創(chuàng)建成員內(nèi)部類的實例荞估,因為成員內(nèi)部類需要依賴外部類的對象
// 通常情況下稀余,我們不建議這樣來
Outer.Inner inner = outer.new Inner();
inner.print();
}
}
class Outer{
private String name;
class Inner{
public void print(){
System.out.println("inner");
}
}
}
建議在外部類中定義一個方法爪飘,對外提供訪問內(nèi)部類的接口
public class Test1 {
public static void main(String[] args){
Outer outer = new Outer();
outer.innerPrint();
}
}
class Outer{
private String name;
// 建議在外部類中定義一個方法,對外提供訪問內(nèi)部類的接口
public void innerPrint(){
Inner inner = new Inner();
inner.print();
}
private class Inner{
public void print(){
System.out.println("inner");
}
}
}
二贺归、方法內(nèi)部類
方法內(nèi)部類只能在定義該內(nèi)部類的方法內(nèi)實例化。不可以在此方法外對其實例化除破。
方法內(nèi)部類對象不能使用該內(nèi)部類所在方法的非final局部變量牧氮。
public class Test1 {
public static void main(String[] args){
Outer outer = new Outer();
outer.show();
}
}
class Outer{
// show方法的局部變量或方法的參數(shù),實際必須是常量 final
public void show(){
final int x = 2;
class Inner2{
public void print(){
//x++瑰枫;// 從內(nèi)部類引用的本地變量必須是最終變量或?qū)嶋H上的最終變量
System.out.println("方法內(nèi)部類"+x);
}
}
Inner2 inner2 = new Inner2();
inner2.print();
}
}
三踱葛、靜態(tài)內(nèi)部類
??在一個類內(nèi)部定義一個靜態(tài)內(nèi)部類。靜態(tài)內(nèi)部類的含義是該內(nèi)部類可以像其他靜態(tài)成員一樣光坝,沒有外部對象時尸诽,也能夠訪問它。靜態(tài)嵌套類僅能訪問外部類的靜態(tài)成員和方法盯另。
public class Test1 {
public static void main(String[] args){
Outer.Inner inner = new Outer.Inner();
inner.show();
}
}
class Outer{
static private String name = "aiguo";
static public void say(){
System.out.println("could say");
}
static class Inner{
public void show(){
System.out.println(name);
say();
}
}
}
四性含、匿名內(nèi)部類
??匿名內(nèi)部類就是沒有名字的內(nèi)部類。
??匿名內(nèi)部類有三種情況:
??(1)鸳惯、集成式匿名內(nèi)部類
public class Test1 {
public static void main(String[] args){
Outer outer = new Outer();
outer.print1();
}
}
class Outer{
// 繼承式
public void print1(){
Cat cat = new Cat() {
public void eat() {
System.out.println("集成式匿名內(nèi)部類");
}
};
cat.eat();
}
}
abstract class Cat{
public abstract void eat();
}
??(2)商蕴、接口式匿名內(nèi)部類
public class Test1 {
public static void main(String[] args){
Outer outer = new Outer();
outer.print2();
}
}
class Outer{
// 接口式
public void print2(){
Eat eat = new Eat() {
public void eat() {
System.out.println("接口式匿名內(nèi)部類");
}
};
eat.eat();
}
}
interface Eat{
public void eat();
}
??(3)、參數(shù)式匿名內(nèi)部類
public class Test1 {
public static void main(String[] args){
Outer outer = new Outer();
outer.print3(new Eat(){
public void eat(){
System.out.println("參數(shù)式匿名內(nèi)部類");
}
});
}
}
class Outer{
public void print3(Eat eat){
eat.eat();
}
}
interface Eat{
public void eat();
}
??在使用匿名內(nèi)部類時芝发,要記住下面幾個原則:
??(1)绪商、不能有構(gòu)造方法,只能有一個實例
??(2)辅鲸、不能定義任何靜態(tài)成員
??(3)格郁、不能使用public,protected独悴,private例书,static
??(4)、一定是在new的后面刻炒,用其隱含實現(xiàn)一個接口或?qū)崿F(xiàn)一個類决采。
??(5)、匿名內(nèi)部類為局部的落蝙,所以局部內(nèi)部類的所有限制對其生效织狐。
五、問題:局部內(nèi)部類訪問局部變量必須用final修飾筏勒,為什么?
??當調(diào)用這個方法時旺嬉,局部變量如果沒有final修飾管行,它的生命周期和方法的生命周期是一樣的,當方法調(diào)用時會入棧邪媳,方法結(jié)束后會彈棧捐顷,這個局部變量也會消失荡陷,那么如果局部內(nèi)部類的對象還沒馬上消息想用這個局部變量,顯然已無法使用了迅涮,如果用final修飾會在類加載的時候進入常量池废赞,即使方法彈棧,常量池的常量還在叮姑,也就可以繼續(xù)使用了唉地。
??注意??:在jdk1.8中取消了在局部內(nèi)部類中使用變量必須顯式的使用final修飾,編譯器默認會為這個變量加上final传透。
六耘沼、內(nèi)部類的作用
??每個內(nèi)部類都能獨立的繼承自一個(接口的)實現(xiàn),所以無論外部類是否已經(jīng)繼承了某個(接口的)實現(xiàn)朱盐,對于內(nèi)部類都沒有影響群嗤。如果沒有內(nèi)部類提供的可以繼承多個具體的或抽象的類的能力,一些設計與編程問題就很難解決兵琳。從這個角度看狂秘,內(nèi)部類是的多重繼承的解決方法變得完整。接口解決了部分問題躯肌,而內(nèi)部類有效的實現(xiàn)了“多重繼承”者春。
成員 局部
成員內(nèi)部類 方法內(nèi)部類
靜態(tài)內(nèi)部類 匿名內(nèi)部類
依賴外部類對象的:成員內(nèi)部類 、方法內(nèi)部類羡榴、匿名內(nèi)部類
靜態(tài)內(nèi)部類不依賴外部類的對象碧查。所以,我們在項目中優(yōu)先考慮靜態(tài)內(nèi)部類(不會產(chǎn)生內(nèi)存泄漏)