Java內部類總結
Java內部類其實在J2EE編程中使用較少,不過在窗口應用編程中特別常見,主要用來事件的處理。其實,作非GUI編程,內部類徹底能夠不用。
內部類的聲明、訪問控制等於外部類有所不一樣,要靈活使用內部類來編寫程序,仍是有至關難度的,Java發明了這種難懂的玩意兒,在其餘語言中是沒有的,可是在Java中,內部類也至關的重要,尤爲作GUI開發時候,事件的響應處理全靠內部類了。
內部類所作的功能使用外部類也一樣能夠實現,只是有時候內部類作的更巧妙些。
內部類按照其所在位置不一樣,可分爲如下幾種:
一、(普通的)內部類(最多見的內部類,內部類的定義與類成員平級,)
二、方法內部類
三、匿名類
四、靜態內部類
五、接口內部類
1、內部類聲明與訪問
一、內部類直接在類的內部進行聲明。能夠聲明爲private、protected、public或者默認訪問權限,這個訪問權限約定和外部類徹底同樣。
二、內部類自動擁有對其外圍類全部成員(方法、屬性)的訪問權。若是內部類和外部類成員的名字徹底相同,在內部類方法中要訪問外部類成員,則須要使用下面的方式來訪問:
外部類名.this.外部成員名,例如Outer.this.i++; (看例子)
三、必須使用外部類對象來建立內部類對象,而不是直接去new一個。
格式爲:
外部對象名.new 內部類構造方法
好比要建立一個內部類iner對象,須要這麼作:
Outer outer = new Outer();
Outer.Inner iner = outer.new Inner();
/**
* 內部類建立與初始化
*
* @author leizhimin 2009-7-17 13:51:52
*/
public
class Outer {
private
int i = 10;
private
int y = 8;
Outer() {
System.out.println(
"調用Outer構造方法:outer");
}
public
void sayMsg() {
System.out.println(
"Outer class!");
}
class Inner {
int i = 1000;
Inner() {
System.out.println(
"調用Inner構造方法:inner");
}
void innerMsg() {
System.out.println(
">>>>>Inner class!");
sayMsg();
//訪問內部類本身的成員i,也能夠寫成 this.i++
this.i++;
//訪問外部類的成員 i和y
Outer.
this.i++;
y--;
}
int getI() {
return i;
}
}
public
void test() {
Inner in =
new Inner();
in.innerMsg();
}
public
int getI() {
return i;
}
public
void setI(
int i) {
this.i = i;
}
}
class Test1 {
public
static
void main(String[] args) {
Outer outer =
new Outer();
outer.test();
System.out.println(outer.getI());
System.out.println(
"-------1--------");
Outer.Inner iner = outer.
new Inner();
iner.innerMsg();
System.out.println(iner.getI());
System.out.println(
"-------2--------");
System.out.println(outer.getI());
}
}
運行結果:
調用Outer構造方法:outer
調用Inner構造方法:inner
>>>>>Inner
class!
Outer
class!
11
-------1--------
調用Inner構造方法:inner
>>>>>Inner
class!
Outer
class!
1001
-------2--------
12
Process finished with exit code 0
2、內部類與接口
一、內部類能夠實現接口。
二、內部類之間相互可見,但並不是內部類之間方法均可見。
public
interface Foo{
void say();
}
public
interface Bar {
void readme();
}
/**
* 內部類實現接口
*
* @author leizhimin 2009-7-17 14:57:50
*/
public
class Test2 {
public
static
void main(String[] args) {
Outer outer =
new Outer();
Foo f = outer.genFoo();
Bar b = outer.genBar();
f.say();
b.readme();
}
}
class Outer {
private
class FooImpl
implements Foo {
public
void say() {
System.out.println(
"say foo!");
}
}
private
class BarImpl
implements Bar {
public
void readme() {
System.out.println(
"say bar!");
}
}
public Foo genFoo() {
return
new FooImpl();
}
public Bar genBar() {
return
new BarImpl();
}
}
輸入結果:
say foo!
say bar!
Process finished with exit code 0
3、訪問權限
外部類分兩種:
一種嵌入了內部類聲明代碼外部類,稱爲直接外部類。
另外一種是與內部類沒有任何關係的外部類,稱爲外部類。
在同一個直接外部類中,內部類之間全部的方法都是相互可見的,包含在直接外部類的main()中可見。
在外部類中,要看到一個類的內部類成員,則至少要求這個內部類的class和成員權限大於或等於protected。
/**
* 內部類實現接口
*
* @author leizhimin 2009-7-17 14:57:50
*/
public
class Test2 {
public
static
void main(String[] args) {
Outer o =
new Outer();
Outer.Bar b = o.genBar();
b.readme();
}
}
class Outer {
protected
class Foo {
protected
void say() {
System.out.println(
"say foo!");
}
private
void test() {
System.out.println(
"----test------");
}
}
protected
class Bar {
protected
void readme() {
System.out.println(
"say bar!");
new Foo().test();
}
}
public Foo genFoo() {
return
new Foo();
}
public Bar genBar() {
return
new Bar();
}
}
4、方法內部類
方法內部類只在該方法內部可見,方法內部類能夠定義在方法中的任何位置。
/**
* 內部類實現接口
*
* @author leizhimin 2009-7-17 14:57:50
*/
public
class Test2 {
public
static
void main(String[] args) {
Outer outer =
new Outer();
Foo f = outer.genFoo();
Bar b = outer.genBar();
f.say();
b.readme();
}
}
class Outer {
public Foo genFoo() {
//方法內的內部類
class FooImpl
implements Foo {
public
void say() {
System.out.println(
"say foo!");
}
}
return
new FooImpl();
}
public Bar genBar() {
Bar b =
null;
if (
true) {
//任意位置的內部類
class BarImpl
implements Bar {
public
void readme() {
System.out.println(
"say bar!");
}
}
b =
new BarImpl();
}
return b;
}
}
運行結果:
say foo!
say bar!
Process finished with exit code 0
5、匿名類
匿名類不給出類名,直接定義一個類,一般這個類實現了某種接口或者抽象。匿名類的訪問權限更沒有討論價值了,看個例子就好了。
在一些多線程程序中比較常見,有點變態,呵呵。
/**
* 匿名類.
*
* @author leizhimin 2009-7-17 15:56:17
*/
public
class Test3 {
public Foo f =
new Foo() {
public
void say() {
System.out.println(
"O(∩_∩)O哈哈~!");
}
};
public Foo test() {
return
new Foo() {
public
void say() {
System.out.println(
"say foo!");
}
};
}
public
static
void main(String[] args) {
Test3 t =
new Test3();
t.f.say();
t.test().say();
}
}
interface Foo {
void say();
}
運行結果:
O(∩_∩)O哈哈~!
say foo!
Process finished with exit code 0
/**
* 普通類的匿名初始化
*
* @author leizhimin 2009-7-17 16:13:31
*/
public
class Fk {
private String x;
public Fk(String x) {
this.x = x;
}
@Override
public String toString() {
return
"Fk{" +
"x='" + x + '\'' +
'}';
}
}
class Test4 {
public Fk hehe() {
//把後面的一對大括號去掉呢,呵呵
return
new Fk(
"fk") {
};
}
public
static
void main(String[] args) {
Test4 t =
new Test4();
Fk f = t.hehe();
System.out.println(f);
}
}
運行結果:
Fk{x='fk'}
Process finished with exit code 0
還有一個不得不提的經典實例,來自thining in java,有改動:
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");}
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);
}
}
這個應用給了咱們不少思考,我就不說了,不一樣人看了會有不一樣的感覺。
內部類的巧妙使用會讓你的代碼很牛,若是要形容下,那就是:沒看懂的時候感受神出鬼沒,看懂後感受鬼斧神工。不過這些代碼多了,別人想看懂都難,想看懂你思路就難上加難了。呵呵!
6、靜態內部類
靜態內部類是static class型的內部類,這種內部類特色是:它不能訪問外部類的非靜態成員。要建立靜態內部類對象時候,也不須要外部類對象了,直接能夠:
new 外部類名.內部類構造方法
來建立,給個例子:
/**
* 靜態內部類
*
* @author leizhimin 2009-7-17 16:53:05
*/
public
class Outer {
public
static
int i =500;
protected
static
class Inner {
int i =100;
String name;
Inner(String name) {
this.name = name;
}
void sayHello() {
System.out.println(
"Hello " + name);
Outer.i++;
}
}
public Inner genInner(String name) {
return
new Inner(name);
}
}
class Test {
public
static
void main(String[] args) {
Outer.Inner in1 =
new Outer.Inner(
"1111");
in1.sayHello();
System.out.println(Outer.i);
Outer.Inner in2 =
new Outer().genInner(
"2222");
in2.sayHello();
System.out.println(Outer.i);
}
}
運行結果:
Hello 1111
501
Hello 2222
502
Process finished with exit code 0
7、接口內部類
接口內部類自動都是public static的,至關於爲接口定義了一種變量類型,這在java的設計中就有使用,好比在HashMap中,就有:
static class Entry<K,V> implements Map.Entry<K,V>
下面我給個例子,
/**
* 接口內部類
*
* @author leizhimin 2009-7-17 17:20:28
*/
public
interface AInterface {
void readme();
class Inner1
implements AInterface {
public
void readme() {
System.out.println(
"我是一個接口內部類");
}
}
}
class Main {
public
static
void main(String[] args) {
AInterface.Inner1 in1 =
new AInterface.Inner1();
in1.readme();
}
}
8、內部的類的嵌套
所謂內部類嵌套,就是內部類裏面再定義內部類。其實這種用法還真沒見過,試試寫個簡單例子看看吧:
/**
* 嵌套內部類
*
* @author leizhimin 2009-7-17 17:33:48
*/
public
class Outer {
private
void f0() {
System.out.println(
"f0");
}
class A {
private
void a() {
f0();
System.out.println(
"a");
}
class B {
protected
void b() {
a();
System.out.println(
"b");
}
}
}
}
class Test{
public
static
void main(String[] args) {
Outer o =
new Outer();
Outer.A a = o.
new A();
Outer.A.B b = a.
new B();
b.b();
}
}
運行結果:
f0
a
b
Process finished with exit code 0
8、內部類的繼承
內部類的繼承,能夠繼承內部類,也能夠繼承外部類。
/**
* 內部類的繼承,能夠繼承內部類,也能夠繼承外部類
*
* @author leizhimin 2009-7-22 13:50:01
*/
public
class Outer {
class Inner {
void doSomething() {
System.out.println(
"Inner doing ...");
}
}
class Inner2
extends Inner {
void doSomething() {
System.out.println(
"Inner2 doing ...");
}
void readme() {
System.out.println(
"HeHe!");
}
}
}
class Test {
public
static
void main(String[] args) {
Outer outer =
new Outer();
Outer.Inner in = outer.
new Inner();
Outer.Inner2 in2 = outer.
new Inner2();
in.doSomething();
in2.doSomething();
in2.readme();
}
}
運行結果:
Inner doing ...
Inner2 doing ...
HeHe!
Process finished with exit code 0
總結:
內部類是Java中最複雜深奧的概念之一,並且內部類在訪問控制,修飾符,繼承,實現,抽象,序列化等等不少方面都是一個很讓人迷惑的問題,在實際中,這些問題也許永遠沒機會沒時間搞清,可是通常說來,懂得以上的內部類的知識就足夠用了。
內部類的設計也許是彌補Java語言自己的先天不足吧,做爲語言來講,這個特性太變態了點,難道就沒別的法了?
以上的總結徹底是創建在實踐基礎上的,所列舉的例子也許偏頗,不能全面反映問題的本質,但願有興趣的博友多多發表本身的見解與觀點。