JAVA为什么要有内部类?

栏目: Java · 发布时间: 9年前

内容简介:JAVA为什么要有内部类?

参考文章:

http://andy136566.iteye.com/blog/1061951/

http://blog.csdn.net/qq7342272/article/details/6671433

本文不会讲解内部类使用的方方面面,比如局部内部类,静态内部类,匿名内部类等的使用可以参考网上资源。本文的目的主要想分析 java 内部类的作用,下面针对每个作用会配备相应的例子来进行说明。

一. 定义

定义在一个类内部的类叫内部类。

二. 作用

1. 实现隐藏,封装性。

2. 非静态内部类拥有其所在外部类的所有元素的访问权限。

3. 利用内部类实现多重继承。

4.实现回调功能。

三. 例子

1. 实现隐藏,封装性

内部类可以很好的实现隐藏,隐藏你不想让别人知道的操作,也即封装性。平时我们对类的访问权限,都是通过类前面的访问修饰符来限制的,一般的非内部类,是不允许有 privateprotected 权限的,但内部类可以,所以我们可以通过内部类来隐藏我们的信息,实现更好的封装。可以看下面的例子:

1.1 定义一个接口:

package org.light4j.j2se.study.innerClass.hidden;

public interface Interface {
    void test();
}

1.2 编写具体类

package org.light4j.j2se.study.innerClass.hidden;

public class Example {

    private class InsideClass implements Interface {
        public void test() {
            System.out.println("这是一个测试");
        }
    }

    public Interface getIn() {
        return new InsideClass();
    }
}

代码解释

内部类的访问修饰符是 private

1.3 编写测试类

package org.light4j.j2se.study.innerClass.hidden;

public class TestExample {

    public static void main(String args[]) {
        Example a = new Example();
        Interface a1 = a.getIn();
        a1.test();
    }
}

代码解释:

从这段代码里面我只知道 ExamplegetIn() 方法能返回一个 Interface 实例,但我并不知道这个实例是这么实现的。而且由于 InsideClassprivate 的,所以我们如果不看代码的话根本看不到这个具体类的名字,所以说它可以很好的实现隐藏。

2. 非静态内部类拥有其所在外部类的所有元素的访问权限

非静态内部类对象有着指向其外部类对象的引用, 一个非静态内部类对象可以访问创建它的外部类对象的内容,甚至包括私有变量!

这是一个非常有用的特性,为我们在设计时提供了更多的思路和捷径。

Java 编译器在创建内部类对象时,隐式的把其外部类对象的引用也传了进去并一直保存着。这样就使得内部类对象始终可以访问其外部类对象,同时这也是为什么在外部类作用范围之外想要创建内部类对象必须先创建其外部类对象的原因,看下面的例子:

package org.light4j.j2se.study.innerClass.access;

public class TagBean {

    private String name = "liutao";

    private class InTest {
        public InTest() {
            System.out.println(name);
        }
    }

    public void test() {
        new InTest();
    }

    public static void main(String args[]) {
        TagBean bb = new TagBean();
        bb.test();
    }
}

代码解释:

代码中的 name 这个变量是在 TagBean 里面定义的 private 私有变量。这个变量在内部类中可以访问, System.out.println(name);

3. 利用内部类实现多重继承

java 中的内部类和接口加在一起,可以的解决常被 C++ 程序员抱怨 java 中没有多继承的问题 。实际上, C++ 的多继承设计起来很复杂,而 java 通过内部类加上接口,可以很好的实现多继承的效果。

这个特点非常重要,它是内部类存在的最大理由之一。正是由于他的存在使得 Java 的继承机制更加完善。大家都知道 Java 只能继承一个类,它的多重继承在我们没有学习内部类之前是用接口来实现的。但使用接口有时候有很多不方便的地方。比如我们实现一个接口就必须实现它里面的所有方法。而有了内部类就不一样了,通过内部类加上接口可以很好的实现多继承的效果。它可以使我们的类继承多个具体类或抽象类。看下面的例子。

3.1 编写类 Example1

package org.light4j.j2se.study.innerClass.multiExtends;

public class Example1 {

    public String name() {
        return "longjiazuo";
    }
}

3.2 编写类 Example2

package org.light4j.j2se.study.innerClass.multiExtends;

public class Example2 {

    public String address() {
        return "beijing";
    }
}

3.3 编写类 MainExample

package org.light4j.j2se.study.innerClass.multiExtends;

public class MainExample {
    private class test1 extends Example1 {
        public String name() {
            return super.name();
        }
    }

    private class test2 extends Example2 {
        public String address() {
            return super.address();
        }
    }

    public String name() {
        return new test1().name();
    }

    public String age() {
        return new test2().address();
    }

    public static void main(String args[]) {
        MainExample mi = new MainExample();
        System.out.println("姓名:" + mi.name());
        System.out.println("地址:" + mi.age());
    }
}

代码解释:

该类里面分别实现了两个内部类 test1 ,和 test2test1 类又继承了 Example1test2 继承了 Example2 ,这样 MainExample 就拥有了 Example1Example2 的方法和属性,也就间接地实现了多继承。

4.实现回调功能。

先说说回调,回调就是某个方法一旦获得了内部类对象的引用之后,就可以在合适的时候反过来去调用外部类实例的方法,也即允许客户类通过内部类引用调用外部类的方法。这种功能非常的灵活。

如果你设计一个类,需要实现一个接口,还需要继承一个类,但是要实现的这个接口和要继承的类中有个一模一样的方法,但是它们的含义是不一样的,你应该怎么办?如何区分这两个同名方法?这时候,你可以建一个内部类实现这个接口。由于内部类对外部类的所有内容都是可访问的,所以这样做可以完成所有你直接实现这个接口的功能,看看下面的例子:

4.1 编写接口 Incrementable

package org.light4j.j2se.study.innerClass.sameMethod;

public interface Incrementable {
    void increment();
}

4.2 编写类 MyIncrement

package org.light4j.j2se.study.innerClass.sameMethod;

public class MyIncrement {

    public void increment() {
        System.out.println("Other increment()");
    }

    static void f(MyIncrement f) {
        f.increment();
    }
}

大家看上面的接口和类有一个一模一样的方法。现在有个类要实现和继承这两个类。如果不用内部类的形式如下所示:

package org.light4j.j2se.study.innerClass.sameMethod;

public class Callee2 extends MyIncrement implements Incrementable {
    public void increment() {
        // 代码
    }
}

上面的 increment() 这个方法是属于覆盖 MyIncrement 这里的方法呢?还是 Incrementable 这里的方法。我怎么能调到 MyIncrement 这里的方法?显然这是不好区分的。而我们如果用内部类就很好解决这一问题了。看下面代码:

package org.light4j.j2se.study.innerClass.sameMethod;

public class Callee2 extends MyIncrement {
    private int i = 0;

    private void incr() {
        i++;
        System.out.println(i);
    }

    private class Closure implements Incrementable {
        public void increment() {
            incr();
        }
    }

    Incrementable getCallbackReference() {
        return new Closure();
    }
}

我们可以用内部类来实现接口,这样就不会与外部类的方法冲突了,上面的实现方式也就是回调。

四. 源代码示例

github 地址: 点击查看

码云地址: 点击查看

欢迎关注人生设计师的微信公众账号

公众号ID:longjiazuoA JAVA为什么要有内部类?

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Using Google App Engine

Using Google App Engine

Charles Severance / O'Reilly Media / 2009-5-23 / USD 29.99

With this book, you can build exciting, scalable web applications quickly and confidently, using Google App Engine - even if you have little or no experience in programming or web development. App Eng......一起来看看 《Using Google App Engine》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

html转js在线工具
html转js在线工具

html转js在线工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具