Java内部类用途和用法

一、为什么需要内部类?

java内部类有什么好处?为什么需要内部类?
首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时候,你可以建一个内部类实现这个接口。由于内部类对外部类的所有内容都是可访问的,所以这
样做可以完成所有你直接实现这个接口的功能。
不过你可能要质疑,更改一下方法的不就行了吗?
的确,以此作为设计内部类的理由,实在没有说服力。
真正的原因是这样的,java中的内部类和接口加在一起,可以的解决常被C++程序员抱怨java中存在的一个问题 没有多继承。实际上,C++的多继承设计起来很复杂,而java通过内部类加上接口,可以很好的实现多继承的效果。

二、内部类的基本定义

在类的内部可以定义成员变量和方法,而且在类的内部也可以定义另一个类,如果类Outer的内部在定义一个类Inner,此时Inner就成为内部类,而Outer则称为外部类。
内部类可以声明为public或private。当内部类声明为public或private,对其访问权限于成员变量和成员方法完全相同。

代码如下:

package com.se.innerclass;
class Outer {
    private String info = "我爱你中国";
    class Inner{
        public void print() {
            System.out.println(info);
        }
    }
    public void fun() {
        new Inner().print();
    }
}
public class InnerClassDemo1 {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.fun();
    }
}

输出结果:
《Java内部类用途和用法》

以上的程序中可以清楚的发现,Inner类作为Outer类的内部类存在,并且外部类的fun()方法中直接实例化内部类的对象调用方法print(),但是从代码中可以明显发现,内部类的存在实际上破坏了一个类的基本结构,因为类是由属性及方法组成的,所以这是内部类的一个缺点,那么内部类有哪些优点呢,如果把内部类拿到外面来就能发现内部类的优点了。
如下面的代码:

package com.se.innerclass;

class Outer {
    private String info = "我爱你中国";
    public void fun() {
        new Inner(this).print();
    }
    public String getInfo(){
        return info;
    }
}
class Inner{
    private Outer outer;
    public Inner(Outer outer){
        this.outer = outer;
    }
    public void print() {
        System.out.println(outer.getInfo());
    }
}
public class InnerClassDemo2 {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.fun();
    }
}

以上程序完成了内部类同样的功能,但是但是代码明显比之前的更加复杂,所以内部类的唯一好处就是可以方便的访问外部类的私有属性。

三、使用static定义外部类

使用static可以声明属性或方法,而使用static也可以声明内部类,用static声明内部类变成了外部类,但是用static声明的内部类不能访问非static的外部类属性。

package com.se.innerclass;

class Outer{
    private static String info = "我爱你中国";
    static class Inner{
        public void print() {
            System.out.println(info);
        }
    }
}
public class InnerClassDemo3{
    public static void main(String[] args) {
        new Outer.Inner().print();
    }
}

以上程序将info属性定义成了static类型,这样程序中就可以通过static声明的内部类直接访问此static属性,当然,如果此时info属性不是static类型,则编译时将出现以下错误:《Java内部类用途和用法》

四、在外部类访问内部类

一个内部类除了可以通过外部类访问,也可以直接在其他类当中调用,调用的基本格式为:
外部类.内部类 内部类对象 = 外部类实例.new 内部类()
以上的操作格式中,首先要找到外部类的实例化对象之后才可以通过外部类的实例化对象去实例化内部类对象。
这里我们可以观察到编译之后的内部类的.class文件。
内部类定义之后,生成的.class文件是以Outer$Inner的形式存在的,在Java中只要文件存在$,则在程序中应将其替换为”.”。
在外部访问内部类代码如下:

package com.se.innerclass;

class Outer{
    private String info = "我爱你中国";
    class Inner{
        public void print() {
            System.out.println(info);
        }
    }
}

public class InnerClassDemo4 {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();
        inner.print();
    }
}



五、在方法中定义内部类

也可以在方法类定义一个内部类,但是在方法中定义的内部类不能直接访问方法中的参数,如果方法中的参数要想被内部类所访问,则参数前必须加上final关键字。
在方法中定义内部类:

package com.se.innerclass;

class Outer{
    private String info = "我爱你中国";
    public void fun(final String temp){
        class Inner{
            public void print(){
                System.out.println(info);
                System.out.println(temp);
            }
        }
        new Inner().print();
    }
}

public class InnerClassDemo5 {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.fun("123");
    }
}

六、匿名内部类
在java中处理内部类之外,还有一种匿名内部类。匿名内部类就是指没有一个具体名称的类,此概念是在接口和抽象类的应用上发展起来的,那么匿名内部类有哪些作用呢?
一个简单的操作:

package com.se.innerclass;
/** * 普通实现 * @author wzy * */
interface A {
    public void printInfo();
}
class B implements A{
    @Override
    public void printInfo() {
        System.out.println("Hello world!!!");       
    }
}
class X{
    public void fun1(){
        this.fun2(new B());
    }
    public void fun2(A a){
        a.printInfo();
    }
}
public class NoInnerClassDemo6 {
    public static void main(String[] args) {
        new X().fun1();
    }
}

通过以上的方法可以实现相应的功能,但是现在如果接口实现类只使用一次,那么还有必要单独定义一个子类B吗?很显然是没有必要的,所以此时就可以使用匿名内部类完成,代码修改如下:

package com.se.innerclass;
interface A{
    public void printInfo();
}
class X{
    public void fun1() {
        this.fun2(new A(){
            @Override
            public void printInfo() {
                System.out.println("hello world");
            }});
    }
    public void fun2(A a) {
        a.printInfo();
    }
}
public class NoInnerClassDemo7 {
    public static void main(String[] args) {
        new X().fun1();
    }
}

七、内部类的扩展

在接口内部可以添加抽象类,在抽象类内部可以添加接口,由于使用较少,不做过多介绍。

    原文作者:编程路漫漫
    原文地址: https://blog.csdn.net/weixin_42899466/article/details/82705062
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞