• 基础篇:JAVA内部类的使用介绍


    1 四种内部类

    • 成员内部类
    • 静态内部类
    • 局部内部类
    • 匿名内部类

    2 内部类的使用场景和优点

    • 内部类的优点:每个内部类都能独立地继承一个类(实现多个接口),无论外部类是否已经继承或者实现,对于内部类都没有影响。内部类的存在使得Java的多继承机制变得更加完善
    • 在开发设计中会存在一些使用接口很难解决的问题,而类却只能继承一个父类。这个时候可以利用内部类去继承其他父类,及implements多个接口能力来解决。内部类使得多重继承的解决方案变得更加完整
    public class HashMap<K,V> extends AbstractMap<K,V>
        implements Map<K,V>, Cloneable, Serializable {
        ...
        //HashMap为了让键元素key具有集合的功能,而继承AbstractSet
        final class KeySet extends AbstractSet<K>{
          ....
        }
        ...
    }

    3 成员内部类

    public class OutClass {
        String name = "OutClass";
        static String nickName = "out";
        void hello(){}
        static void hi(){}
        //InnerClass就像OutClass内部成员一样可以访问name、nickName属性|hello(),hi()
        class InnerClass{
            String innerName = "InnerClass";
            void test(){
                System.out.println(innerName);
                System.out.println(name);
                System.out.println(nickName);
                hello();
                hi();
            }
        }
    }
    • 成员内部类就像外部类的普通成员一样,可以访问外部类的属性及方法
    • 成员内部类内部不允许存在任何静态变量或静态方法(static);因为成员内部类是属于对象的,而静态变量、静态方法会先于外部类的对象存在,因此不允许成员内部类存在静态属性、方法
    • 成员内部类如果需在外部类的外部使用,则需通过调用外部类对象的普通方法创建
    public class OutClass {
        public class InnerClass{}
        //只能在非静态方法返回InnerClass 实例
        public InnerClass getInnerClass(){
            return new InnerClass();
        }
    }
    ----调用外部类对象的普通方法获取内部类
    OutClass outClass = new OutClass();
    OutClass.InnerClass innerClass =  outClass.getInnerClass();

    4 成员内部类的访问范围详解

    public class OutClass{
        class InnerClass{}
    }
    • 编译器在进行编译的时候,会将成员内部类单独编译成一个字节码文件,下面是 OutClass.java 的代码
    • javap -v OutClass$InnerClass 反编译 OutClass$InnerClass.class,可以看反编译的一段代码如下:
    //OutClass$InnerClass.class
      final com.OutClass this$0;  //InnerClass 存在一个指向外部类对象的引用
        descriptor: Lcom/OutClass;
        flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
    • 可以看出成员内部类对象的创建依赖外部类的实例对象,在没有外部类实例之前是无法创建内部类的。因为非静态内部类对象存在一个指向外部类对象的引用;也因此成员内部类可以在随意访问外部类的成员

    5 静态内部类

    public class OutClass {
        String name = "OutClass";
        static String nickName = "out";
        void hello(){}
        static void hi(){}
        static class StaticInnerClass{
            String innerName = "staticInnerClass";
            static String staticName = "staticName";
            //无法使用OutClass的普通属性和普通方法,静态的可以
            void test(){
                System.out.println(innerName);
                System.out.println(nickName);
                System.out.println(staticName);
                hi();
            }
            static void staticTest(){ }
        }
    • 用static修饰的内部类称之为静态内部类,静态内部类和非静态内部类之间存在一个最大的区别;非静态内部类在编译完成之后会隐含的保存着一个引用,该引用是指向创建它的外围类,但是静态类没有
    • 静态内部类的创建不需要依赖外部类可以直接创建
    • 静态内部类不可以使用任何外部类的非static属性和方法
    • 静态内部类可以存在自己的成员变量包括非静态和静态属性和方法

    6 局部内部类

    public class Test {
        public static void main(String[] args) {
            sayHello("shu");
        }
        static void  sayHello(String hello){
            //InnerClass的访问范围和sayHello访问范围一致
            class InnerClass {
                public void run(String name){
                    System.out.println(name);
                    System.out.println(hello);
                }
            }
            InnerClass innerClass = new InnerClass();
            innerClass.run("hello");
        }
    }
    • 方法内部类不允许使用访问权限修饰符;public、private、protected均不允许
    • 方法内部类对外部完全隐藏,除了创建这个类的方法可以访问它以外,其他地方均不能访问
    • 方法的访问区域范围就是方法内部类可以访问的区域范围

    7 匿名内部类

    interface CInterface {  void test(); }
    class Outer{
        public void hello(CInterface cInterface) {
            cInterface.test();
        }
    }
    public class Test {
        public static void main(String[] args) {
            Outer outer = new Outer();
            outer.hello(new CInterface(){
                public void test(){
                    System.out.println("test CInterface");
                }
            });
        }
    }  
    • 匿名内部类就是一个没有名字的方法内部类,因此特点和方法与方法内部类完全一致
    • 匿名内部类必须继承一个抽象类或者实现一个接口
    • 匿名内部类没有类名,因此没有构造方法
    • 匿名内部类使得编码更加简洁

    欢迎指正文中错误

    关注公众号,一起交流

    参考文章

  • 相关阅读:
    EasyDSS视频平台定制项目中普通用户登录无法全局搜索出文件的排查及优化
    EasyDSS前端代码运行npm install命令报错如何处理?
    运行EasyDSS前端代码报错Can't find Python executable“python”如何处理?
    EasyDSS视频平台前端点播服务列表跨页新增水印不展示第二页数据优化
    EasyDSS视频平台点播服务选中点播文件删除失败分析及排查
    EasyDSS视频平台下载录像由于ts文件原因导致MP4文件缺秒问题优化
    ffmpeg推流到服务器如何通过EasyDSS视频平台将视频保存为文件?
    EasyDSS视频平台是如何对直播流和点播流做处理的?
    EasyDSS视频平台点播页选中视频通道进行导出表单操作无反应排查
    如何允许EasyDSS在线课堂系统上传点播文件时文件名带有空格?
  • 原文地址:https://www.cnblogs.com/cscw/p/13591320.html
Copyright © 2020-2023  润新知