#Thinking in Java阅读笔记# 第十章 内部类

来源:互联网 发布:达内2017java视频下载 编辑:程序博客网 时间:2024/05/17 06:59

创建内部类

内部类的创建:把内部类的定义放置在外部类的定义之中,在非静态方法中创建内部类时,内部类的使用就和组合类一样。但是在非静态方法之外的部分创建内部类,必须要对内部类的对象变量声明为:OuterClassName.InnerClassName

public class TestJava {    class inner{        public void print() {            System.out.println("inner");        };    }    public inner test() {        return new inner();//返回内部类的引用    }    public static void main(String[] args) {        TestJava t = new TestJava();        TestJava.inner i = t.test();//OuterClassName.InnerClassName        i.print();    }}

链接到外部类

在外部类对象创建一个内部类对象时,内部类对象会捕捉到外部类对象的引用,从而使得内部类能通过这个引用来使用外部类中的任意成员(域和方法),从而使得内部类与创造它的外部类之间有一种联系(1.内部类对象有外部类对象的引用 2.内部类的创建依赖于外部类(比如外部类中有方法返回内部类,如上述))。内部类只有在与其外部类对象相关联的情况下才能被创建(即内部类不为static)。

内部类对象为何能直接访问外部类成员?
1 编译器自动为内部类添加一个成员变量, 这个成员变量的类型和外部类的类型相同, 这个成员变量就是指向外部类对象的引用;
2 编译器自动为内部类的构造方法添加一个参数, 参数的类型是外部类的类型, 在构造方法内部使用这个参数为1中添加的成员变量赋值;
3 在调用内部类的构造函数初始化内部类对象时, 会默认传入外部类的引用。

使用.this/.new

1.如果要生成外部类的引用,可以使用OuterClassName.this

public class TestJava {    class inner{        public TestJava r() {            return TestJava.this;//返回外部类的引用        }    }    public void print() {        System.out.println("OuterClass");    }    public inner test() {        return new inner();//返回内部类的引用    }    public static void main(String[] args) {        TestJava t = new TestJava();        TestJava.inner i = t.test();//OuterClassName.InnerClassName        i.r().print();//return TestJava的引用,再调用外部类的print()方法    }}

2.如果想直接创建内部类的对象(而不是通过调用外部类的函数),则需要使用外部类的对象来创建内部类的对象,用外部类对象的引用调用.new语法,内部类对象的创建一定要基于外部类之上

public class TestJava {    class inner{        public inner() {            System.out.println("Inner");        }    }    public static void main(String[] args) {        TestJava t = new TestJava();        TestJava.inner i = t.new inner();//告知外部类对象创建内部类对象,则需要提供外部类的引用来调用.new    }}

内部类可以直接访问外部类的成员:

public class TestJava {    private String s;    class inner{        public void str() {            s = "123";//外部类的成员可以直接访问,甚至是Private            print();            System.out.println(s);        }    }    private void print() {        System.out.println("outer");    }    public static void main(String[] args) {        TestJava t = new TestJava();        t.new inner().str();    }}

而外部类需要建立内部类的实例后才能访问内部类的成员:

public class TestJava {    class inner{        private String s;        private void print() {            this.s = "Hello"+s;            System.out.println(s);        }    }    public void outer() {        inner i = new inner();        i.s = " World!";//需要构建内部类实例        i.print();    }    public static void main(String[] args) {        TestJava t = new TestJava();        t.outer();    }}

内部类与向上转型

用内部类实现了某接口,可以方便的向上转型,从而很好的隐藏实现细节。

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

局部内部类:在一个方法中插入内部类

interface itf{    void print();    void out();}public class Test{    public itf inner(){        class in implements itf{            public void print(){                System.out.print("Inner");            }            public void out(){                System.out.print("out");            }        }    return new in();    }    public static void main(String[] args){        Test t = new Test;        t.inner().print();      }这个内部类的作用域就是在此方法内,外部无法看见。这种方式可以方便的实现itf接口,从而让Test类通过只调用函数自身的函数来得到不同实现的接口。

匿名内部类

匿名内部类,没有名字,所以它没有构造器(因为构造器要求和类同名),可以实现一个接口或者扩展于一个类:
1.实现于接口时,一定不能传递参数给它,因为接口没有构造器。
格式:

new InterfaceType(){    methods and data;}public class TestJava {    ActionListener listener = new ActionListener() {        public void actionPerform() {            System.out.println("1");        }    };}

2.扩展于某类时,如果其基类的构造函数需要传递参数,则需要将参数加入new Class(…)中,如果此参数只用于基类的构造器,则不用设定为final,如果内部类中需要使用此参数,则需要设定为final

new SuperType(constructor parameters){    methods and data;}class Sup{    private int i;    public Sup(int x) {this.i = x;}    public int value() {return i;}}public class TestJava {    public Sup test(int x) {        return new Sup(x) {//自动调用基类的构造器            public int value() {                return super.value() * 47;            }        };    }    public static void main(String[] args) {        TestJava t = new TestJava();        System.out.println(t.test(5).value());    }}
原创粉丝点击