Java 中的内部类

前言

在第一次把Java 编程思想中的内部类这一章撸完后,有点印象。大概知道了什么时内部类,局部内部类,匿名内部类,嵌套内部类。随着时间的推移,本身慢慢的就忘记了,总感受本身思考的东西很少,因而 看了第二遍,并把本身的想法和一些笔记写下来。供之后参考。java

内部类

定义:若是把A类定义再B类里面,那么把A类叫作 内部类编程

代码以下:ide

public class B {
	public class A{}
}

复制代码

这样看内部类是否是感受很简单?定义确实很简单,可是思考一下,这样定义一个内部类有什么意义吗?或者说能带来什么好处? 上面那样定义,我的感受是意义不大。因此 ,咱们通常定义内部类,都是须要内部类实现一个接口或着抽象类。有实际意义的代码以下(例子来自,java编程思想):测试

/** * @ClassName Selector * @Description 选择器 * @Author ouyangkang * @Date 2019-03-12 14:21 **/
public interface Selector {

    // 是否结束
    boolean end();

    // 当前数据
    Object current();

    // 下一个节点
    void next();
}
复制代码
/** * @ClassName Squence * @Description TODO * @Author ouyangkang * @Date 2019-03-12 14:24 **/
public class Squence {

    private Object[] items;

    private int next;

    public Squence(int size) {
        items = new Object[size];
    }

    public void add(Object x) {
        if (next < items.length) {
            items[next++] = x;
        }
    }

    private class SequceneSelector implements Selector {

        private int i;

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

class Test{
    public static void main(String[] args) {
        Squence squence = new Squence(10);
        for (int i = 0; i < 10 ; i++) {
            squence.add(i);
        }
        // 调用内部类 这是迭代器模式的一个例子。 经过内部类 ,访问类中的私有属性。
        Selector selector = squence.selector();
        while (!selector.end()){
            System.out.print(selector.current()+" ");
            selector.next();
        }
    }
}

复制代码

输出: 0 1 2 3 4 5 6 7 8 9this

请仔细查看上面代码。 这是个很是好的例子。访问权限为 private 的内部类 SequceneSelector 实现了 Selector 接口 ,该内部类能够访问外部类 Squence 中私有属性 items 。 并提供一个公开的方法 selector ,返回一个,向上转型为 Selector 类型。 在测试代码中。先建立 squence 对象。 往里面添加10个元素。 并调用该对象的中的 selector() 方法,返回一个 Selector 类型的对象。 根据咱们定义的 Selector 接口中方法的含义,编码。打印输出。编码

上面代码说明了内部类的几个好处:spa

  1. 隐藏了细节,实现一个接口,向上转型。
  2. 能够访问外部类中的全部私有属性,方法。就像是拥有他们同样。可是不是拥有(你能够把它想成一个成员方法)

我以为第一点没什么好说的,反却是第二点,本身是这样理解的:外部类就像是一个房子,里面的成员变量,方法,内部类。就像是房子里面的人。能够相互通讯。而内部类实现了一个接口或着抽象类后,就有点像细做同样,表面看起来是房子里面的人,其实真正是外面的人。只要我建立它,并经过向上转型,就能够到外面去通讯。code

局部内部类

定义: 若是把A类定义再B类的方法中,那么把A类叫作局部内部类对象

代码以下:接口

public class A {
    private void getB(){
    	class B{}
    }

}
复制代码

其实上面代码意义并不大。 下面看下一些有意义的代码。代码以下:

/** * @InterfaceName Destination * @Description TODO * @Author ouyangkang * @Date 2019-03-12 19:59 **/
public interface Destination {
    String readLabel();
}
复制代码
/** * @ClassName Parcel * @Description TODO * @Author ouyangkang * @Date 2019-03-12 20:00 **/
public class Parcel {
    public Destination destination(String str){
        class PDestination implements Destination{

            private String label = str;

            public PDestination(String label){
                this.label = label;
            }
            @Override
            public String readLabel() {
                return label;
            }
        }
        return new PDestination(str);
    }

    public static void main(String[] args) {
        Parcel parcel = new Parcel();
        Destination destination = parcel.destination("hello");
        System.out.println(destination.readLabel());
    }
}
复制代码

输出 hello

定义一个为 Destination 的接口,方法为 readLabel() 。 Parcel 类中定义了一个 返回 Destination 类型的方法。 该方法中定义了一个 PDestination 类,并实现了 Destination 接口。 在最后返回PDestination 的对象。 上面局部内部类很熟悉把。下面,咱们看下匿名内部类。

匿名内部类

将上面Parcel类修改 ,代码以下

/** * @ClassName Parcel1 * @Description TODO * @Author ouyangkang * @Date 2019-03-13 15:33 **/
public class Parcel1 {

    public Destination destination(final String str){
        return new Destination() {
            private String label = str;
            @Override
            public String readLabel() {
                return label;
            }
        };
    }

    public static void main(String[] args) {
        Parcel1 parcel1 = new Parcel1();
        Destination ouyangkang = parcel1.destination("hello");
        System.out.println(ouyangkang.readLabel());
    }
}
复制代码

输出:hello

Parce1 中的 destination() 方法直接 new 了一个 Destination 对象,重写该 readLabel() 方法。 这样返回没有名字的局部内部类类,称为匿名内部类。

局部内部类 VS 匿名内部类

在使用局部内部类或着匿名内部类的时候,要使用外部类中的局部变量是,该变量要为final ,要问为为何,由于局部内部类或着匿名内部类内部对局部变量操做并不会改变改内容,因此为了防止使用错误。就用final修饰。不可变。其根本缘由就是不会有任何的变化。 那么何时用局部内部类,何时用匿名内部类? 在你须要一个已命名的构造器,或着须要重构构造器。须要的不止是该一个内部类对象。就是你要定义多个构造器的时候用局部内部类。若是不须要就用匿名内部类。 JAVA 8 能够用Lambda 表达式表示 上面 Parcel1 类 用 JAVA 8 编码以下

public class Parcel2 {

    public Destination destination(final String str) {
        return ()->{
            String label = str;
            return label;
        };
    }

    public static void main(String[] args) {
        Parcel2 parcel2 = new Parcel2();
        Destination ouyangkang = parcel2.destination("hello");
        System.out.println(ouyangkang.readLabel());
    }

   
}
复制代码

输出:hello

嵌套类

若是把A类定义在B类中,并A类用static关键字修饰,那么把A叫作嵌套类。 代码以下:

publc class B{
	static class A{}
}
复制代码

若是不须要内部类和外部类有关系,就把该内部类声明为 static 。 建立嵌套类表明:

  1. 并不须要外围类对象
  2. 不能从嵌套类的对象中访问外部类中的 非静态的东西。

我通常用嵌套类来作测试类。嵌套类理解就到此为止了

总结

总的来讲,Java 中的 内部类并无想象的的那么难理解和认知,可是内部类使用起来就比较深奥了,其中多态这一特性在,配合着内部类,可谓说贼强了。隐藏细节,关注接口中方法自己的意思。

相关文章
相关标签/搜索