《JAVA编程思想》之《内部类》笔记

甩手一张思维导图

这里写图片描述


1.内部类的概述

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


10.1创建内部类

  • 代码实例:
public class Outer {

   public Outer() {
        System.out.println("实例化Outer.Outer");
    }

    class Inner {
        public Inner() {
            System.out.println("实例化我的时候,同时也实例化了外围类(Outer),Inner.Inner");
        }
    }

    static class InnerStatic {

        public InnerStatic() {
            System.out.println("实例化我时,并没有实例化外围类InnerStatic.InnerStatic");
        }
    }


    public Inner inners() {
        return new Inner();
    }

    public static void main(String[] args) {
        Outer outer = new Outer();
        Inner inners = outer.inners();
        Outer.InnerStatic innerStatic = new InnerStatic();
    }
}
//打印的log日志
实例化Outer.Outer
实例化我的时候,同时也实例化了外围类(Outer),Inner.Inner
实例化我时,并没有实例化外围类InnerStatic.InnerStatic

Process finished with exit code 0

main()方法中可以看到,从外部类(Outer)调用非静态的内部类时,必须通过外部类的引用来实例出Inner对象来。反之,静态内部类就不需要通过外部类的引用,直接就可以实例InnerStatic对象。 可以看出,静态内部类是相对于独立,非静态内部类依赖于外部类的引用。

从打印Log日志
非静态内部类,实例被创建的时候,它和外围实例之前的关联也随之被简历起来,而且,这种关联关系以后不能被修改。这种关联需要消耗非静态成员类实例的控件,并且增加了构造的时间开销。
静态成员类,它可以访问外围类的任何静态成员,包括哪些声明为私有的成员。静态成员类时外围类的一个静态成员,与其他的静态成员一样,也遵守同样的可访问性的规则

10.2链接到外部类

interface Selector {

    boolean end();

    Object current();

    void next();

}


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;
        }
    }
//创建私有的非静态内部类,并且实现 Selector 接口
    private class SequenceSelcetor implements Selector {

        private int i = 0;

        @Override
        public boolean end() {
            return i == items.length;//这句话表达内部类可以使用外围类的所有成员
        }

        @Override
        public Object current() {
            return items[i];
        }

        @Override
        public void next() {
            if (i < items.length)
                i++;
        }
    }


    public Selector selector() {
        return new SequenceSelcetor();
    }


    public static void main(String[] args) {
    //实例创建Sequence对象
        Sequence sequence = new Sequence(10);
        for (int i = 0; i < sequence.items.length; i++) {
            sequence.add(Integer.toString(i));
        }
//通过外围类的引用,实例创建成员类Selector对象
        Selector selector = sequence.selector();
        while (!selector.end()) {
            System.out.print(selector.current() + " ");
            selector.next();
        }
    }
}

其实看上面代码,主要讲:当生成一个内部了的对象时,此对象与制造它的外围类之间就有了一种联系,所以它能访问其外围对象的所有成员,而不需要任何特殊条件。此外内部类还拥有其外围类的所有元素的访问权。

10.3 使用.this与.new

package ten;

/**
 * Created by Administrator on 2017/8/11.
 */
public class DotThis {
    void f() {
        System.out.println("f()");
    }

    public class Inner {
        public DotThis dotThis() {
            return DotThis.this;
        }

        public DotThis newDotThis() {
            return new DotThis();
        }
    }

    public Inner inner() {
        return new Inner();
    }

    public static void main(String[] args) {

        DotThis dotThis = new DotThis();
//        DotThis.Inner dot = dotThis.new Inner();
        System.out.println("dotThis = " + dotThis.toString());
        DotThis.Inner dot = dotThis.inner();
        System.out.println("dot = " + dot.toString());
        DotThis dotThis1 = dot.dotThis();
        System.out.println("dotThis1 = " + dotThis1.toString());
        DotThis newDotThis = dot.newDotThis();
        System.out.println("newDotThis = " + newDotThis.toString());

    }
}
//Log日志:
dotThis = ten.DotThis@1540e19d
dot = ten.DotThis$Inner@677327b6
dotThis1 = ten.DotThis@1540e19d
newDotThis = ten.DotThis@14ae5a5

Process finished with exit code 0

从日志可以看出,首先27行实例创建DotThis()对象,30行通过外围类DotThis() 的引用,实例成员类Inner()的对象,32行通过成员类的引用来调用内部的doThis()方法,实例外围类DotThis()对象,34行同样是,通过成员类的引用调用内部的newDoThis()方法,实例一个新的外围DotThis()对象。
1.有时候可能想要告知某些其他对像,去创建其某个内部类的对象。要实现此目的,必须在new表达式中提供对其他外部类对象的引用,就像28行那样。
2.要想创建内部类的对象,必须通过外部类的对象来创建内部类对象,同时也解决了内部类名字作用域的问题。
3.在拥有外部类对象之前是不可能创建内部类对象的,这是因为内部类对象会暗暗地连接到创建它的外部类对象上。但是,如果创建的是嵌套类(静态内部类),那么就不需要对外部类对象的引用。

10.4内部类与向上转型

  1. 介绍:当内部了向上转型为其基类,尤其是转型为一个接口的时候,内部类就有了用武之地。(从实现了某个接口的独享,得到对此接口的引用,与向上转型为这个对象的基类,实质上效果是一样的。)这好似因为此内部类——某个接口的实现——能够完全不可见,并且不肯用。所得到的只是指向基类或几口的引用。
/**
 * Created by Administrator on 2017/8/14.
 */
interface Contents {

    int value();

}

/**
 * Created by Administrator on 2017/8/14.
 */
interface Destination {

    String readLabel();

}


/**
 * Created by Administrator on 2017/8/14.
 * Parce4.class
 */
public class Parce4 {

    //定义私有的Pcontents,并实现Contents接口,只有 Parce4能够访问该类
    private class PContents implements Contents {

        private int i = 11;

        @Override
        public int value() {
            return i;
        }
    }

    //定义受保护的PDestination,并实现Destination接口,只有在同一个包类可能访问,不局限于Parce4
    protected class PDestination implements Destination {

        private String label;

        public PDestination(String label) {
            this.label = label;
        }

        @Override
        public String readLabel() {
            return label;
        }

    }

//该方法可以返回 Destination对象,或者 Destination 子类
    public Destination destination(String s) {
        return new PDestination(s);
    }

    //该方法可以返回 Contents对象,或者 Contents 子类
    public Contents contents() {
        return new PContents();
    }

}


/**
 * Created by Administrator on 2017/8/14.
 * TestParcel.class
 */
public class TestParcel {


    public static void main(String[] args) {

        Parce4 parce4 = new Parce4();

        Contents contents = parce4.contents();

        //向上转型,destination方法返回的是PDestination对象
        Destination destination = parce4.destination("testLable");

    }
}

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

  1. 一个定义在方法中的类
  2. 一个定义在作用域内的类,此作用域在方法的内部。
  3. 一个实现了将诶口的匿名类。
  4. 一个匿名类,它扩展了有非默认构造器的类。
  5. 一个匿名类,它执行字段初始化
  6. 一个匿名类,它通过实例初始化实现构造(匿名类不可能有构造器)

展示代码局部内部类实例:

/**
 * Created by Administrator on 2017/8/14.
 */
public class Parcel5 {

    public Destination destination(String s) {

        int i = 0;//局部变量

        //局部内部类
        class PDestination implements Destination {

            private String label;

            public PDestination(String label) {
                this.label = label;
            }

            @Override
            public String readLabel() {
                return label;
            }
        }
        return new PDestination(s);
    }


    public static void main(String[] args) {
        Parcel5 parce5 = new Parcel5();
        Destination destination = parce5.destination("testmain");
    }
}

展示作用域内嵌入类

public class Parcel5 {

    private void internalTracking(boolean b) {
        if (b) {
        //该类嵌入在if语句的作用域内, 给我的感觉,很少用
            class TrackingSlip {
                private String id;

                public TrackingSlip(String id) {
                    this.id = id;
                }

                String getSlip() {
                    return id;
                }
            }
        }
    }
}

10.6匿名内部类

匿名内部类


/**
 * Created by Administrator on 2017/8/14.
 */
public class Parcel6 {

    //1.第一种 匿名内部类
    public Contents contents() {

        return new Contents() {
            private int i = 11;

            @Override
            public Object value() {
                return i;
            }

        };

    }


    //2.第二种 创建一个实现Contents的匿名类的对象,通过new表达式返回的引用被自动想和桑转型为Contents的阴雨哦给你。
    class MyContents implements Contents {

        private int i = 12;

        @Override
        public Object value() {
            return i;
        }
    }

    public Contents contents1() {
        return new MyContents();
    }

    public static void main(String[] args) {

        Parcel6 parcel6 = new Parcel6();
        Contents contents = parcel6.contents();
        Object value = contents.value();
        System.out.println("value = " + value);
        Contents contents1 = parcel6.contents1();
    }

}
10.6.1再访工厂方法
interface Service {
    void method1();

    void method2();
}

interface ServiceFactroy {

    Service getService();
}

class Implementation1 implements Service {

    public Implementation1() {

    }

    @Override
    public void method1() {
        System.out.println("Implementation1.method1");
    }

    @Override
    public void method2() {
        System.out.println("Implementation1.method2");

    }

    public static ServiceFactroy serviceFactroy = new ServiceFactroy() {
        @Override
        public Service getService() {
            return new Implementation1();
        }
    };

}

class Implementation2 implements Service {

    public Implementation2() {
    }

    @Override
    public void method1() {
        System.out.println("Implementation2.method1");
    }

    @Override
    public void method2() {
        System.out.println("Implementation2.method2");
    }

    public static ServiceFactroy serviceFactroy = new ServiceFactroy() {
        @Override
        public Service getService() {
            return new Implementation2();
        }
    };

}


public class Factories {

    public static void serviceConsumer(ServiceFactroy factroy) {
        Service s = factroy.getService();
        s.method1();
        s.method2();
    }


    public static void main(String[] args) {
        serviceConsumer(Implementation1.serviceFactroy);
        serviceConsumer(Implementation2.serviceFactroy);
    }


}

10.7嵌套类

  • 所谓嵌套类,就是与外部类之间没有联系,并且嵌套类的声明是static。普通的内部类对象隐式地保存了一个引用,指向创建它的外围类对象。然而,当内部类是static就不是这样了。
    1. 要创建嵌套类的对象,并不需要其外围类的对象。
    2. 不能从嵌套类的对象中访问非静态的外围类对象。

嵌套类与普通的内部类还有一个区别。
- 普遍内部类的字段与方法,只能在类的外部层次上,所以普通的内部类不能有static数据和static字段,也不能包含嵌套类。
- 嵌套类可以包含所有这些东西:




/**
 * Created by Administrator on 2017/8/14.
 */
public class Parcel11 {

    //私有的ParcelContents嵌套类
    private static class ParcelContents implements Contents {

        private int i = 10;

        @Override
        public Object value() {
            return i;
        }
    }

    //私有的ParcelDestination嵌套类
    protected static class ParcelDestination implements Destination {

        private String label;

        public ParcelDestination(String label) {
            this.label = label;
        }

        @Override
        public String readLabel() {
            return label;
        }


        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 contents = contents();

        Destination d = destination("tasmania");

    }

}
10.7.1接口内部的类

/**
 * Created by Administrator on 2017/8/9.
 */
public interface ClassInInterface {

    void howdy();

    //内部类实现外部接口,放到接口类中的任何类都自动地是public和static的
    class TestClase implements ClassInInterface {

        @Override
        public void howdy() {
            System.out.println("TestClase.howdy");
        }

        public static void testStatic(ClassInInterface classInInterface) {
            System.out.println("TestClase.testStatic");
            classInInterface.howdy();

        }

        public static void main(String[] args) {

            new TestClase().howdy();
            testStatic(new TestClase());
        }
    }
}

10.7.2从多层嵌套类中访问外部类的成员

一个内部类被嵌套多少层并不重要——它能透明地访问所有他所嵌入的外围类的所有成员

/**
 * Created by Administrator on 2017/8/14.
 */

class MNA {
    private void f() {
    }

    class A {
        private void g() {
        }

        public class B {
            void h() {
                f();
                g();
            }
        }
    }
}

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();
    }
}

10.8为什么需要内部类

一般说来,内部类继承自某个类或实现某个接口,内部类的代码操作创建爱你它的外围类的对象。所以可以认为内部类提供了某种进入其外围类的窗口。
每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。

/**
 * Created by Administrator on 2017/8/14.
 */


public class MultiInterfaces {
    interface A {
    }

    interface B {
    }

    static class X implements A, B {
    }

    static class Y implements A {

        B makeB() {
            return new B() {
            };
        }
    }

    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);
        takesB(y.makeB());
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怀君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值