巧妙的理解掌握Java内部类

01 前言编程

 

       昨天晚上,我把车停好之后就回家了。回家后才发现手机落在车里面了,但外面太冷,冷到骨头都能感觉到寒意——实在是不想返回一趟去取了(小区的安保还不错,不用担忧被砸车玻璃),因而打定主意过几个小时的“世外桃源”生活——别人找不到我,我也找不到别人,这种与世隔绝的状态很是适合读书写做。
       把厚厚的《Java编程思想》摆在桌子上,正襟危坐,认认真真地读起了第十章——内部类。尽管我已经很是耐心和用心了,但内部类的这一章很是的枯燥,而且难以理解,我整我的几乎处于崩溃的边缘。
       很早以前,有想要转行学习Java的朋友咨询我,有哪方面的书能够推荐,我郑重其事地介绍了《Java编程思想》,而且一再叮嘱他这是一本Java入门级的经典书,必须耐着性子读完它。如今想一想,本身当时的推荐真是轻率!
       我这样说,并非为了否定《Java编程思想》这本书的价值,由于站在书本的角度,它可能会感慨说:这王二的学习能力有问题啊,读我居然这么困难!
       不是有那样一句话嘛:“若是你手里有一把锤子,全部东西看上去都像钉子。”我认为“内部类”这一章很难懂,其根本的缘由在于我对“内部类”没有很好的理解。想要继续扎实Java的基础知识,惟一要作的就是——想尽一切办法搞懂“内部类”,并梳理成文。闭包

 

02 内部类的定义ide

 

       顾名思义,内部类就是放在另一个类的内部定义的类。很是重要的一点是,内部类可以访问外部类的全部成员,包括private修饰的。
来看程序清单1-1:

 

public class Wanger {
    private int age;
    public Wanger(int age) {
        this.age = age;
    }
    class Thought {
        public void know() {
            System.out.println("沉默王二的年龄" + age);
        }
    }
    public Thought getThought() {
        return new Thought();
    }
    public static void main(String[] args) {
        Wanger wanger = new Wanger(29);
        Wanger.Thought thought = wanger.getThought();
        thought.know(); // 输出:沉默王二的年龄29
        // 使用.new的形式建立内部类对象
        Wanger.Thought thought1 = wanger.new Thought();
        thought1.know();
    }
}

 

程序清单1-1要表达什么意思呢?
       答案是:我,沉默王二,已经29岁了,89年出生(有人说89年出生明明是30岁)。上了年纪了,总想装点嫩,理解一下。我读书很少,但特别爱思考,因而我就给本身建立了一个会思考的内部类Thought。
       答从程序清单1-1能够看得出,尽管Thought是内部类,但能够访问外部类Wanger的私有成员变量age。
       答若是想建立内部类的对象,须要先指明对象引用的类型,格式为OuterClassName.InnerClassName,就像main()方法中的Wanger.Thought那样。
       答紧接着,就要来建立内部类对象了,有两种形式。第一种形式是先在外部类中定义一个方法Thought getThought(),返回使用new关键字建立的内部类对象,而后使用外部类对象调用该方法wanger.getThought();第二种形式是直接经过外部类对象.new建立wanger.new Thought()。函数

 

03 匿名内部类学习

 

       答以个人编程经验来看,匿名内部类使用最频繁的场合就是在建立线程的时候。
来看程序清单2-1:this

 

public class Demo {
    public void test(String title) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                // title = "我不要吃鸡";
                // 改变时会提示错误
                // 在封闭范围中定义的局部变量必须是final的。
                System.out.println(title);
            }
        });
        thread.start();
    }
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Demo demo = new Demo();
            demo.test("我要吃鸡" + i);
        }
    }
}

 

       在程序清单2-1中,test()方法内部有一个线程对象thread,是经过new Thread()建立的。new Thread()能够接收一个实现了Runnable接口类型的对象,这个对象要怎么建立呢?能够经过匿名内部类的形式来建立——new Runnable() {public void run(){......}}——这段简短的代码等同于:.net

 

// 实现Runnable接口
class MyRunnable implements Runnable {
    @Override
    public void run() {
    }
}
// 向上转型
Runnable myRunnable = new MyRunnable();

 

       匿名内部类的好处就在于不只节省了定义实现类的过程,还可以自动向上转型。
       在程序清单2-1中,test()方法还有一个参数title,JDK1.8以前,编译器要求它必须是final类型的。但JDK1.8以后,若是咱们在匿名内部类中须要访问局部变量,那么这个局部变量再也不须要用final关键字修饰了。
       但若是想要在匿名内部类中改变局部变量的值,编译器就会提醒你不能这样作,它会提示:“在封闭范围中定义的局部变量必须是final的。”线程


04 为何须要内部类对象


       Java的内部类让我很容易的想起来JavaScript的闭包,闭包就是定义在一个函数内部的函数——这听起来和Java的内部类定义同样同样的。本质上,闭包是将函数内部与函数外部链接起来的桥梁。内部类同样,它是将内部类与外部类链接起来的桥梁。
来看看什么是闭包吧:blog

 

function wanger() {
    var age = 30;
    function know() {
        console.log(age);
    }
}
wanger();
// 控制台输出30

       除此以外,内部类最引人注意的缘由是:        内部类能够独立地继承一个抽象类或者实现一个接口,不管外部类是否也这样作了,对内部类都没有影响。        总而言之,内部类让类的内容丰富多彩,就好像一我的的心中还能够住着另一我的。

相关文章
相关标签/搜索