需要了解2個概念:內(nèi)部類和靜態(tài)修飾符static
1)首先,用內(nèi)部類是因為內(nèi)部類與所在外部類有一定的關(guān)系,往往只有該外部類調(diào)用此內(nèi)部類。所以沒有必要專門用一個Java文件存放這個類。
2)靜態(tài)都是用來修飾類的內(nèi)部成員的。比如靜態(tài)方法,靜態(tài)成員變量,靜態(tài)常量。它唯一的作用就是隨著類的加載(而不是隨著對象的產(chǎn)生)而產(chǎn)生,以致可以用類名+靜態(tài)成員名直接獲得。
這樣靜態(tài)內(nèi)部類就可以理解了,因為這個類沒有必要單獨存放一個文件,它一般來說只被所在外部類使用。并且它可以直接被用 外部類名+內(nèi)部類名 獲得。
以下舉例說明怎么使用:
Student類有個叫School的內(nèi)部類(非靜態(tài))
Student stu = new Student();
stu.School sch = new stu.School();
sch就是School的一個對象。
假如School是內(nèi)部靜態(tài)類:
Student.School sch = new Student.School();
外創(chuàng)建內(nèi)部類就是把類定義至于外圍類的里面
靜態(tài)方法在JVM剛加載的時候就編譯過了...在程序的運行過程中隨時可以調(diào)用...不需要去實例化某個對象然后再去調(diào)用...可以直接用類名去調(diào)用...不過你想一下,在JVM剛加載的進修就編譯過了..也就是說它一直存在著...也就是說它一直占用這內(nèi)存中的地址空間...所以說也是比較占資源的噢!
相對于靜態(tài)方法而言,動態(tài)方法占的內(nèi)存資源就少些...因為它是什么時候使用什么時候?qū)嵗?..也就是說在不使用的時候它是不會占用資源的...相對與靜態(tài)方法的缺點是它每次使用的時候都要進行實例化...也就是說比較麻煩一些了...
- public class Parcel1 {
- class Destination {
- private String label;
-
- Destination(String whereTo) {
- label = whereTo;
- }
-
- String readLabel() {
- return label;
- }
- }
-
- //在類的的函數(shù)中使用內(nèi)部類,與使用普通類沒多大區(qū)別
- public void ship(String dest) {
- Destination d = new Destination(dest);
- System.out.println(d.readLabel());
- }
-
- public static void main(String[] args) {
- Parcel1 p = new Parcel1();
- p.ship("Tasmania");
- }
- }
public class Parcel1 {class Destination {private String label;Destination(String whereTo) {label = whereTo;}String readLabel() {return label;}}//在類的的函數(shù)中使用內(nèi)部類,與使用普通類沒多大區(qū)別public void ship(String dest) {Destination d = new Destination(dest);System.out.println(d.readLabel());}public static void main(String[] args) {Parcel1 p = new Parcel1();p.ship("Tasmania");}}
如果想從外部類的非靜態(tài)方法之外的任意位置創(chuàng)建某個內(nèi)部類的對象,必須具體地知名這個對象餓類型(OuterClassName.InnerClassName),比如
- public class Parcel2 {
- class Contents {
- private int i = 11;
-
- public int value() {
- return i;
- }
- }
-
- public Contents contents() {
- return new Contents();
- }
-
- public void ship(String dest) {
- Contents c = contents();
- Destination d = to(dest);
- System.out.println(d.readLabel());
- }
-
- public static void main(String[] args) {
- Parcel2 p = new Parcel2();
- p.ship("Tasmania");
- Parcel2 q = new Parcel2();
- // Defining references to inner classes:
- Parcel2.Contents c = q.contents();
- }
- }
public class Parcel2 {class Contents {private int i = 11;public int value() {return i;}}public Contents contents() {return new Contents();}public void ship(String dest) {Contents c = contents();Destination d = to(dest);System.out.println(d.readLabel());}public static void main(String[] args) {Parcel2 p = new Parcel2();p.ship("Tasmania");Parcel2 q = new Parcel2();// Defining references to inner classes:Parcel2.Contents c = q.contents();}}
外部類擁有其外圍類的所有元素的訪問權(quán)
如果你需要生成對外部類對象的引用,可以使用外部類的名字后面緊跟圓點和this,如下:
- public class DotThis {
- void f() {
- System.out.println("DotThis.f()");
- }
-
- public class Inner {
- public DotThis outer() {
- //通過外部類名字后面緊跟遠點和this獲取外部類對象 //的引用
- return DotThis.this;
- }
- }
-
- public Inner inner() {
- return new Inner();
- }
-
- public static void main(String[] args) {
- DotThis dt = new DotThis();
- DotThis.Inner dti = dt.inner();
- //通過獲取到的外部類調(diào)用外部類中的方法
- dti.outer().f();
- }
- }
public class DotThis {void f() {System.out.println("DotThis.f()");}public class Inner {public DotThis outer() {//通過外部類名字后面緊跟遠點和this獲取外部類對象 //的引用return DotThis.this;}}public Inner inner() {return new Inner();}public static void main(String[] args) {DotThis dt = new DotThis();DotThis.Inner dti = dt.inner();//通過獲取到的外部類調(diào)用外部類中的方法dti.outer().f();}}
如果你要在main函數(shù)中創(chuàng)建一個內(nèi)部類對象,你必須在new表達式中提供對其他外部類對象的引用,這是需要使用.new語法,比如上例代碼在main中修改創(chuàng)建內(nèi)部類Inner對象的方法改為DotThis.Inner dti = dt.new Inner()后效果一樣
在擁有外部類對象之前是不可能創(chuàng)建內(nèi)部類對象,因為內(nèi)部類對象會暗暗地連接到創(chuàng)建它的外部類對象上,但是如果你創(chuàng)建的是嵌套類(靜態(tài)內(nèi)部類),就不需要對外部類對象的引用
在方法的作用域內(nèi)(而不是在其他類的作用域內(nèi))創(chuàng)建一個完整的類.這被稱作局部內(nèi)部類:
- public interface Destination {
- String readLabel();
- }
public interface Destination {String readLabel();}
- public class Parcel5 {
- public Destination destination(String s) {
- class PDestination implements Destination {
- private String label;
-
- private PDestination(String whereTo) {
- label = whereTo;
- }
-
- public String readLabel() {
- return label;
- }
- }
- return new PDestination(s);
- }
-
- public static void main(String[] args) {
- Parcel5 p = new Parcel5();
- Destination d = p.destination("Tasmania");
- }
- }
public class Parcel5 {public Destination destination(String s) {class PDestination implements Destination {private String label;private PDestination(String whereTo) {label = whereTo;}public String readLabel() {return label;}}return new PDestination(s);}public static void main(String[] args) {Parcel5 p = new Parcel5();Destination d = p.destination("Tasmania");}}
PDestination類是destination()方法的一部分,所以在destination()之外不能訪問,在return語句中的向上轉(zhuǎn)型,返回的是Destination的引用,是一個基類
你也可以再同一個子目錄下的任意類中對某個內(nèi)部類使用類標示符PDestination,因為定義在方法內(nèi)部,所以不會出現(xiàn)命名沖突.
在任意的作用域內(nèi)嵌入一個內(nèi)部類,比如在if語句的作用域內(nèi):
- public class Parcel6 {
- private void internalTracking(boolean b) {
- if (b) {
- class TrackingSlip {
- private String id;
- TrackingSlip(String s) {
- id = s;
- }
- String getSlip() {
- return id;
- }
- }
- TrackingSlip ts = new TrackingSlip("slip");
- String s = ts.getSlip();
- }
- }
- public void track() {
- internalTracking(true);
- }
- public static void main(String[] args) {
- Parcel6 p = new Parcel6();
- p.track();
- }
- }
public class Parcel6 {private void internalTracking(boolean b) {if (b) {class TrackingSlip {private String id;TrackingSlip(String s) {id = s;}String getSlip() {return id;}}TrackingSlip ts = new TrackingSlip("slip");String s = ts.getSlip();}}public void track() {internalTracking(true);}public static void main(String[] args) {Parcel6 p = new Parcel6();p.track();}}
這并不是說該類的創(chuàng)建時有條件的,它其實與別的類一起編譯過了,然而,在定義TrackingSlip的作用域之外,它是不可用的,除此之外,與普通的類一樣
匿名內(nèi)部類,一直看起來有點奇怪
- public interface Contents {
- int value();
- }
public interface Contents {int value();}
- public class Parcel7 {
- public Contents contents() {
- return new Contents() {
- private int i = 11;
- public int value() {
- return i;
- }
- };
- }
- public static void main(String[] args) {
- Parcel7 p = new Parcel7();
- Contents c = p.contents();
- System.out.println(c.value());
- }
- }
public class Parcel7 {public Contents contents() {return new Contents() {private int i = 11;public int value() {return i;}};}public static void main(String[] args) {Parcel7 p = new Parcel7();Contents c = p.contents();System.out.println(c.value());}}
將返回值的生成與表示這個返回值的類的定義結(jié)合在一起,另外這個類是匿名的, 它沒有名字.其實匿名類是非匿名類,然后去實現(xiàn)一個接口的簡化形式
如果定義一個匿名內(nèi)部類,并且希望它使用一個在其外部定義的對象,那么編譯器會要求其參數(shù)引用時final的
- public interface Destination {
- String readLabel();
- }
public interface Destination {String readLabel();}
- public class Parcel9 {
- //參數(shù)dest必須定義成final的,才能在匿名內(nèi)部類中使用
- public Destination destination(final String dest) {
- return new Destination() {
- private String label = dest;
- public String readLabel() {
- return label;
- }
- };
- }
- public static void main(String[] args) {
- Parcel9 p = new Parcel9();
- Destination d = p.destination("Tasmania");
- System.out.println(d.readLabel());
- }
- }
public class Parcel9 {//參數(shù)dest必須定義成final的,才能在匿名內(nèi)部類中使用public Destination destination(final String dest) {return new Destination() {private String label = dest;public String readLabel() {return label;}};}public static void main(String[] args) {Parcel9 p = new Parcel9();Destination d = p.destination("Tasmania");System.out.println(d.readLabel());}}
匿名內(nèi)部類不可能有命名構(gòu)造器(因為它根本沒名字),但通過實例初始化,能夠達到為匿名內(nèi)部類創(chuàng)建一個構(gòu)造器的效果
- abstract class Base {
- public Base(int i) {
- System.out.print("Base constructor, i = " + i);
- }
- public abstract void f();
- }
- public class AnonymousConstructor {
- //這里i不用聲明為final,因為不會再匿名內(nèi)部類被直接使用
- public static Base getBase(int i) {
- return new Base(i) {
- {
- System.out.print("Inside instance initializer");
- }
- public void f() {
- System.out.print("In anonymous f()");
- }
- };
- }
- public static void main(String[] args) {
- Base base = getBase(47);
- base.f();
- }
- }
abstract class Base {public Base(int i) {System.out.print("Base constructor, i = " + i);}public abstract void f();}public class AnonymousConstructor {//這里i不用聲明為final,因為不會再匿名內(nèi)部類被直接使用public static Base getBase(int i) {return new Base(i) {{System.out.print("Inside instance initializer");}public void f() {System.out.print("In anonymous f()");}};}public static void main(String[] args) {Base base = getBase(47);base.f();}}
下面來看一段代碼
- public class Parcel10 {
- public Destination destination(final String dest, final float price) {
- return new Destination() {
- private int cost;
- // 這里的if語句不能作為字段初始化的一部分來執(zhí)行
- {
- cost = Math.round(price);
- if (cost > 100)
- System.out.println("Over budget!");
- }
- private String label = dest;
-
- public String readLabel() {
- return label;
- }
- };
- }
-
- public static void main(String[] args) {
- Parcel10 p = new Parcel10();
- Destination d = p.destination("Tasmania", 101.395F);
- }
- }
public class Parcel10 {public Destination destination(final String dest, final float price) {return new Destination() {private int cost;// 這里的if語句不能作為字段初始化的一部分來執(zhí)行{cost = Math.round(price);if (cost > 100)System.out.println("Over budget!");}private String label = dest;public String readLabel() {return label;}};}public static void main(String[] args) {Parcel10 p = new Parcel10();Destination d = p.destination("Tasmania", 101.395F);}}
對于匿名類而言,實例初始化的實際效果就是構(gòu)造器,當然它受到了限制-----不能重載實例化方法,所以你僅有一個這樣的構(gòu)造器
匿名內(nèi)部類與正規(guī)的繼承相比有些受限,因為匿名內(nèi)部類既可以擴展類,也可以實現(xiàn)接口,但是不能兩者兼?zhèn)?而且如果是實現(xiàn)接口,也只能實現(xiàn)一個接口
利用匿名內(nèi)部類,定義工廠方法
- interface Service {
- void method1();
-
- void method2();
- }
-
- interface ServiceFactory {
- Service getService();
- }
-
- class Implementation1 implements Service {
- private Implementation1() {
- }
-
- public void method1() {
- System.out.println("Implementation1 method1");
- }
-
- public void method2() {
- System.out.println("Implementation1 method2");
- }
-
- public static ServiceFactory factory = new ServiceFactory() {
- public Service getService() {
- return new Implementation1();
- }
- };
- }
-
- class Implementation2 implements Service {
- private Implementation2() {
- }
-
- public void method1() {
- System.out.println("Implementation2 method1");
- }
-
- public void method2() {
- System.out.println("Implementation2 method2");
- }
- //利用匿名內(nèi)部類的方式實現(xiàn)一個接口,實現(xiàn)工廠的方式得到當前類
- public static ServiceFactory factory = new ServiceFactory() {
- public Service getService() {
- return new Implementation2();
- }
- };
- }
-
- public class Factories {
- public static void serviceConsumer(ServiceFactory fact) {
- Service s = fact.getService();
- s.method1();
- s.method2();
- }
-
- public static void main(String[] args) {
- serviceConsumer(Implementation1.factory);
- serviceConsumer(Implementation2.factory);
- }
- }
interface Service {void method1();void method2();}interface ServiceFactory {Service getService();}class Implementation1 implements Service {private Implementation1() {}public void method1() {System.out.println("Implementation1 method1");}public void method2() {System.out.println("Implementation1 method2");}public static ServiceFactory factory = new ServiceFactory() {public Service getService() {return new Implementation1();}};}class Implementation2 implements Service {private Implementation2() {}public void method1() {System.out.println("Implementation2 method1");}public void method2() {System.out.println("Implementation2 method2");}//利用匿名內(nèi)部類的方式實現(xiàn)一個接口,實現(xiàn)工廠的方式得到當前類public static ServiceFactory factory = new ServiceFactory() {public Service getService() {return new Implementation2();}};}public class Factories {public static void serviceConsumer(ServiceFactory fact) {Service s = fact.getService();s.method1();s.method2();}public static void main(String[] args) {serviceConsumer(Implementation1.factory);serviceConsumer(Implementation2.factory);}}
建議:優(yōu)先實用類而不是接口,如果你的設(shè)計中需要某個接口,你必須了解它,否則.不到迫不得已,不要將其放到你的設(shè)計中
如果不需要內(nèi)部類對象與其外圍類對象之間有聯(lián)系,那么可以講內(nèi)部類聲明為static.通常稱為嵌套類,當內(nèi)部類是static時,意味著:
[1]要創(chuàng)建嵌套類的對象,并不需要其外圍類的對象
[2]不能從嵌套類的對象中訪問非靜態(tài)的外圍類對象
嵌套類與普通的內(nèi)部類還有一個區(qū)別:普通內(nèi)部類的字段的字段與方法,只能放在類的外部層次上,所以普通的內(nèi)部類不能有static數(shù)據(jù)和static字段,也不能包含嵌套類.但是在嵌套類里可以包含所有這些東西
- public class Parcel11 {
- private static class ParcelContents implements Contents {
- private int i = 11;
- public int value() {
- return i;
- }
- }
- protected static class ParcelDestination implements Destination {
- private String label;
- private ParcelDestination(String whereTo) {
- label = whereTo;
- }
- public String readLabel() {
- return label;
- }
- // 嵌套類可以包括其他靜態(tài)元素
- public static void f() {
- }
- static int x = 10;
- static class AnotherLevel {
- public static void f() {
- }
- static int x = 10;
- }
- }
- public static Destination destination(String s) {
- return new ParcelDestination(s);
- }
- public static Contents contents() {
- return new ParcelContents();
- }
- public static void main(String[] args) {
- Contents c = contents();
- Destination d = destination("Tasmania");
- }
- }
public class Parcel11 { private static class ParcelContents implements Contents { private int i = 11; public int value() { return i; } } protected static class ParcelDestination implements Destination { private String label; private ParcelDestination(String whereTo) { label = whereTo; } public String readLabel() { return label; } // 嵌套類可以包括其他靜態(tài)元素 public static void f() { } static int x = 10; static class AnotherLevel { public static void f() { } static int x = 10; } } public static Destination destination(String s) { return new ParcelDestination(s); } public static Contents contents() { return new ParcelContents(); } public static void main(String[] args) { Contents c = contents(); Destination d = destination("Tasmania"); } }
正常情況下,不能在接口內(nèi)部放置任何代碼,但嵌套類可以作為接口的一部分,你放到接口中的任何類都自動的是public和static.因為類是static,只是將嵌套類至于接口的命名空間內(nèi).你甚至可以再內(nèi)部類中實現(xiàn)其外圍接口
- public interface ClassInInterface {
- void howdy();
-
- class Test implements ClassInInterface {
- public void howdy() {
- System.out.println("Howdy!");
- }
-
- public static void main(String[] args) {
- new Test().howdy();
- }
- }
- }
public interface ClassInInterface { void howdy(); class Test implements ClassInInterface { public void howdy() { System.out.println("Howdy!"); } public static void main(String[] args) { new Test().howdy(); } } }
以前一直不知道,嵌套類竟然可以這樣用
- public class TestBed {
- public void f() { System.out.println("f()"); }
- public static class Tester {
- public static void main(String[] args) {
- TestBed t = new TestBed();
- t.f();
- }
- }
- }
public class TestBed { public void f() { System.out.println("f()"); } public static class Tester { public static void main(String[] args) { TestBed t = new TestBed(); t.f(); } } }
就是可以把main方法放在嵌套類中
一個內(nèi)部類被嵌套多少層不重要,它能透明地訪問所有它所嵌入的外圍類的所有成員,如下
- class MNA {
- private void f() {
- }
- class A {
- private void g() {
- }
- public class B {
- void h() {
- //訪問A對象的g方法
- g();
- //訪問MNA對象的f方法
- f();
- }
- }
- }
- }
-
- public class MultiNestingAccess {
- public static void main(String[] args) {
- MNA mna = new MNA();
- MNA.A mnaa = mna.new A();
- MNA.A.B mnaab = mnaa.new B();
- mnaab.h();
- }
- }