一.創建內部類
(1)內部類瞭解外圍類,並能與之通信
(2)創建內部類方式:把類的定義置於外圍類的裏面
public class Parcel1 {
//內部類1
class Contents{
private int i = 11 ;
public int value(){
return i ;
}
}
//內部類2
class Destination{
private String label ;
Destination(String whereTo){
label = whereTo;
}
String readLabel(){
return label ;
}
}
public void ship(String dest){
//創建內部類
Contents c = new Contents();
Destination d = new Destination(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args) {
Parcel1 p = new Parcel1();
p.ship("Tasmaia");
}
}
二.鏈接到外部類
1.當生成一個內部類的對象時,此對象與製造它的外圍對象之間就有了一種聯繫,所以能訪問其外圍對象的所有成員,而不需要任何條件。內部類還擁有其外圍類所有元素的訪問權。
2.內部類自動擁有對其外圍所有成員的訪問權。
public class Sequence {
private Object[] items ;
private int next = 0 ;
public Sequence(int size){
items = new Object[size];
}
public void add(Object x){
if(next < items.length){
items[next++] = x ;
}
}
//內部類
private class SequenceSelector implements Selector{
private int i = 0 ;
public boolean end() {
//調用外部類的方法 items爲private
return i == items.length;
}
public Object current() {
return items[i];
}
public void next() {
if(i < items.length)
i ++ ;
}
}
public Selector selector(){
//生成內部類對象
return new SequenceSelector();
}
public static void main(String[] args) {
//...
}
}
三.使用.this與.new
public class MainJava {
void f(){
System.out.println("DotThis.f()");
}
public class Inner{
public MainJava outer(){
//內部類生成對外部類對象的引用
return MainJava.this; //MainJava 爲外部類
}
}
public Inner inner(){
return new Inner();
}
public static void main(String[] args) {
MainJava dt = new MainJava();
MainJava.Inner dti = dt.inner();
dti.outer().f();
}
}
//創建內部類對象
public class DotNew{
public class Inner{};
public static void main(String[] args){
DotNew dn = new DotNew(); //生成外部類對象
DotNew.Inner dni = dn.new Inner(); //生成內部類對象
}
}
要想直接創建內部類的對象,你不能按照你想象的方式,去引用外部類的名字DotNew,而是必須使用外部類的對象來創建改內部類對象。
擁有外部類對象之前是不可能創建內部類對象的。
4.內部類與向上轉型
(1)當將內部類向上轉型爲基類,尤其是轉型爲一個接口的時候,內部類就有了用武之地。
5.在方法和作用域內的內部類
可以在一個方法裏面或者在任意的作用域內定義內部類。
6.匿名內部類
(1)不使用匿名內部類
abstract class Person {
public abstract void eat();
}
class Child extends Person {
public void eat() {
System.out.println("eat something");
}
}
public class Demo {
public static void main(String[] args) {
Person p = new Child();
p.eat();
}
}
(2)使用匿名內部類
abstract class Person {
public abstract void eat();
}
public class Demo {
public static void main(String[] args) {
Person p = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
(3)在接口上使用匿名內部類
interface Person {
public void eat();
}
public class Demo {
public static void main(String[] args) {
Person p = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
只要一個類是抽象的或是一個接口,那麼其子類中的方法都可以使用匿名內部類來實現
最常用的情況就是在多線程的實現上,因爲要實現多線程必須繼承Thread類或是繼承Runnable接口
(4)Thread類的匿名內部類實現
public class Demo {
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i + " ");
}
}
};
t.start();
}
}
(5).匿名內部類只能使用一次,它通常用來簡化代碼編寫
(6).但使用匿名內部類還有個前提條件:必須繼承一個父類或實現一個接口
9.爲什麼需要內部類
(1)使用內部類最吸引人的原因是:
每個內部類都能獨立地繼承自一個(接口的)實現,所以無論外圍類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響。
(2)內部類使得多重繼承的解決方案變得完整
//即必須在一個類中以某種方式實現兩個接口。由於接口的靈活性,可以使用單一類或內部類
interface A{}
interface B{}
class X implements A,B{}
class Y implements A {
B makeB(){
return new B(){};
}
}
public class MultiInterfaces{
static void takesA(A a){}
static void takesB(B b){}
public static void main(String[] args){
X x = new X();
Y y = new Y();
takesA(x);
takesA(y);
takesB(x);
}
}
//如果擁有的是抽象的類或具體的類,而不是接口,那就只能使用內部類才能實現多重繼承
class D {}
abstract class E {
abstract void A();
}
class Z extends D {
E makeE(){
//匿名內部類
return new E() {
void A() {
}};
};
}
}
public class MultiImplementation{
static void takesD(D d){}
static void takesE(E e){}
public static void main(String[] args){
Z z = new Z();
takesD(z);
takesE(z.makeE());
}
}