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

18 篇文章 0 订阅

创建内部类

内部类的创建:把内部类的定义放置在外部类的定义之中,在非静态方法中创建内部类时,内部类的使用就和组合类一样。但是在非静态方法之外的部分创建内部类,必须要对内部类的对象变量声明为: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());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值