《java编程思想——第十章(内部类)》

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011067966/article/details/80175052

内部类

可以将一个类的定义放在另一个类的定义内部,这就是内部类。

10.1 创建内部类

把类的定义置于外围类的里面。

/**
 * 创建内部类
 * @author Administrator
 */
public class Parcel1 {
    class Contents{
        private int i = 11;
        public int value() {
            return i;
        }
    }
    class Destination{
        private String label;
        public 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("哈哈");
    }

}

10.2 链接到外部类

内部类自动拥有外部类所有成员的访问权。构建内部类对象时,需要一个指向其外围类对象的引用。

10.3 使用.this和.new

如果想要生成对外部对象的引用,可以用外部类名后跟.this的形式。

public class DotThis {

    void f(){
        System.out.println("DotThis.f()");
    }
    public class Inner {
        public DotThis outer(){
            return DotThis.this;
        }
    }
    public Inner inner() {
        return new Inner();
    }
    public static void main(String[] args) {
        DotThis dt = new DotThis();
        DotThis.Inner dti = dt.inner();
        dti.outer().f();
    }
}

如果要创建内部类的对象,必须在new表达式时提供其外部类的引用。形式是外部类引用.new形式。

public class DotNew {

    public class Inner {}
    public static void main(String[] args) {
        DotNew dn = new DotNew();
        DotNew.Inner dni = dn.new Inner();
    }
}

10.4 内部类与向上转型

内部类向上转型为其基类,或者接口时,所得到的只是指向基类或接口的引用,能够很方便的隐藏细节。

/**
 * 内部类向上转型
 * @author Administrator
 */
class Parcel4{
    private class pContents implements Content{
        private int i = 11;
        @Override
        public int value() {
            return i;
        }

    }
    protected class PDestination implements Destinations{

        private String label;
        public PDestination(String whereTo) {
            label = whereTo;
        }
        public String readLabel(){
            return label;
        }

    }

    public Destinations destinations(String s) {
        return new PDestination(s);
    }
    public Content contents() {
        return new pContents();
    }
}
public class TestParcel {
    public static void main(String[] args) {
        Parcel4 p = new Parcel4();
        Content c = p.contents();
        Destinations d = p.destinations("哈哈");
    }
}

10.5 在方法和作用域的内部类

/**
 * 方法内部类
 * @author Administrator
 *
 */
public class Parcel5 {

    public Destinations destination(String s) {

         class pDestination implements Destinations{

            private String label;
            public pDestination(String whereTo) {
                label = whereTo;
            }
            public String readLabel(){
                return label;
            }

        }
        return new pDestination(s);
    }

}

/**
 * 作用域内部类
 * @author Administrator
 *
 */
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();
    }
}

10.6 匿名内部类

默认构造匿名内部类

/**
 * 匿名内部类
 * @author Administrator
 *
 */
public class Parcel7 {

    public Content  content() {
        return new Content() {
            private int i = 11;
            @Override
            public int value() {
                return i;
            }
        };
    }
    public static void main(String[] args) {
        Parcel7 p = new Parcel7();
        Content c = p.content();
    }
}

带参数匿名内部类

public class Parcel8 {
    public Wrapping  wrapping(int x) {
        return new Wrapping(x) {
            private int i = 11;
            @Override
            public int value() {
                return super.value() * 47;
            }
        };
    }
    public static void main(String[] args) {
        Parcel8 p = new Parcel8();
        Wrapping w = p.wrapping(8) ;
    }
}

匿名内部类如果使用一个在其外部定义的对象,其参数的引用必须是final 的。

10.7 嵌套类

如何不需要内部类和外部类有联系,可以将内部类声明为static,通常称为嵌套类

特性:创建嵌套类的对象,并不需要其外围对象。
不能从嵌套类的对象中访问非静态的外围类对象

  1. 接口中的内部类
    正常情况下接口中不能放置任何代码,但嵌套类可以作为接口中国的一部分。
/**
 * 接口中的内部类
 * @author Administrator
 *
 */
public interface ClassInInterface {
    void howdy();
    class Test implements ClassInInterface{
        @Override
        public void howdy() {
            System.out.println("hai");
        }
        public static void main(String[] args) {
            new Test().howdy();
        }

    }
}

10.8 为什么需要内部类

每个内部类都能独立地继承自一个实现,所以无论外围类是否已经继承了某个实现,对应内部类都没有影响。

  1. 内部类可以有多个实例,每个实例都有自己的状态信息,并且与外部类信息相独立。
  2. 在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或继承同一个类。
  3. 创建内部类对象的时刻并不依赖于外围类对象的创建。

闭包与回调:闭包是一个可调用对象,它记录了一些信息,这些信息来自于创建它的域。
回调的价值在于可以在运行时动态地决定调用什么方法。

内部类与控制框架:
框架的完整实现是由单个类创建,从而使得实现的细节被封装了起来。
内部类能够很容易的访问外围类的任意成员。
(这部分demo无法运行)

10.9 内部类的继承

因为内部类的构造器必须连接到指向其外围类对象的引用,所以在继承内部类的时候,必须用特殊的语法。

/**
 * 内部类的继承
 * @author Administrator
 *
 */
class WithInner{
    class Inner{}
}
public class InheritInner  extends WithInner.Inner{
    public InheritInner(WithInner wi) {
        wi.super(); //初始化
    }
    public static void main(String[] args) {
        WithInner wi = new WithInner();
        InheritInner ii = new InheritInner(wi);
    }
}

10.10 内部类可以别覆盖吗

不能被覆盖。继承了外围类并覆盖了内部类时,两个内部类是是完全独立的实体,各自在自己的命名空间里。
可以明确的继承某一个内部类。

/**
 * 明确继承内部类,覆盖方法
 * @author Administrator
 *
 */
 class Egg2 {

    protected class Yolk{
        public Yolk() {
            System.out.println("Egg2.Yolk()");
        }
        public void f() {
            System.out.println("Egg2.Yolk.f()");
        }
    }
    private Yolk y = new Yolk();
    public Egg2(){
        System.out.println("new Egg2");
    }
    public void insertYolk(Yolk yy) {
        y = yy;
    }
    public void g() {
        y.f();
    }

}
public class BigEgg2 extends Egg2{
    public class Yolk extends Egg2.Yolk{
        public Yolk() {
            System.out.println("BigEgg2.Yolk()");
        }
        public void f() {
            System.out.println("BigEgg2.Yolk.f()");
        }
    }
    public BigEgg2() {
        insertYolk(new Yolk());
    }
    public static void main(String[] args) {
        Egg2 e2 =  new BigEgg2();
        e2.g();
    }
}

10.11 局部内部类

局部内部类可以定义在方法体内,不能有访问说明符,因为它不是外围类的一部分;但是可以访问外围类成员。

/**
 * 局部内部类
 * @author Administrator
 */
interface Counter{
    int next();
}
public class LocalInnerClass {

    private int count = 0;
    Counter getCounter (final String name){
        class LocalCounter implements Counter{
            public LocalCounter() {
                System.out.println("LocalCounter()");
            }
            @Override
            public int next() {
                System.out.println(name +" "+count);
                return count++;
            }

        }
        return new LocalCounter();

    }

    Counter getCounter2 (final String name){
        return new Counter() {
            {
                System.out.println("Counter()");
            }
            @Override
            public int next() {
                System.out.println(name +" "+count);
                return count++;
            }
        };

    }
    public static void main(String[] args) {
        LocalInnerClass lic = new LocalInnerClass();
        Counter c1 = lic.getCounter("Local Inner");
        Counter c2 = lic.getCounter2("Anonymous Inner");

        for (int i = 0; i < 5; i++) {
            c1.next();
        }
        for (int i = 0; i < 5; i++) {
            c2.next();
        }
    }
}

与匿名内部类比较:可以有一个命名的构造器,可以创建不止一个局部内部类对象。

10.12 内部类标识符

每个类都会产生.class文件,内部类也会产生一个.class文件,命名格式:外围类名字+$+内部类名字。

10.13 总结

接口和内部类结合起来就能解决多重继承的问题。

猜你喜欢

转载自blog.csdn.net/u011067966/article/details/80175052