zoukankan      html  css  js  c++  java
  • Java 之内部类

    1. 概述
    2. 内部类修饰符
    3. 内部类的细节
    4. 局部内部类
    5. 匿名内部类及其应用
    6. 匿名内部类细节

    内部类概述

    将一个类定义在另一个类的里面, 里面的那个类就称为内部类(内置类, 嵌套类).

    class Outer
    {   
        class Inner // 内部类
        {
    
        }
    }
    
    class InnerClassDemo
    {
        public static void main(String[] args)
        {
    
        }
    }
    // 上述代码编译完成后, 生成 3 个字节码文件,
    // 分别是: InnerClassDemo.class, Outer$Inner.class, Outer.class
    

    访问特点:

    1. 内部类可以直接访问外部类中的成员, 包括私有成员.
      原因是: 内部类持有了外部类的引用, 外部类名.this (具体请见_内部类的细节_)
    2. 外部类要访问内部类中的成员必须要建立内部类的对象

    应用场景

    • 一般用于类的设计
    • 分析事物时, 发现该事物 A 描述中还有事物 B, 而且这个事物 B 还在访问被描述事物 A 的内容,
      这时,就把事物 B 定义为内部类来描述.

    内部类修饰符

    class Outer
    {
        private int num = 3;
    
        class Inner //内部类
        {
            void show()
            {
                System.out.println("show run..." + num);
            }
    
            /*
            static void function() // 如果内部类中定义类静态成员, 该内部类也必须是静态的
            {
                System.out.println("function run..."+ num);
            }
            */
        }
    }
    
    class InnerClassDemo
    {
        public static void main(String[] args)
        {
            // 直接访问外部类中的内部类成员 (较少见)
            Outer.Inner in = new Outer().new Inner();
            in.show();
    
            // 如果内部类是静态的, 随着外部类的加载而加载, 不需要建立外部类对象
            Outer.Inner in = new Outer.Inner(); // 创建的是内部类对象
            in.show();
    
            // 如果内部类是静态的, 内部类的成员也是静态, 此时, 内部类也不需要创建对象
            Outer.Inner.function();
        }
    }
    
    // 示例: 
    class Demo
    {
        public void func()
        {
            // 位置一
        }
    
        class Inner{}
    
        public static void main(String[] args)
        {
            Demo d = new Demo();
            // 位置二
        }
    }
    A. 在位置1 写 new Inner(); // 可以
    B. 在位置2 写 new Inner(); // 不可以, 因为主函数是静态的, 只能调用静态成员, 所以内部类也必须是 static 的
    C. 在位置2 写 new d.Inner(); // new new Demo().Inner(); 格式错误, 正确格式: new Demo().new Inner();
    D. 在位置2 写 new Demo.Inner(); // 格式正确, 但是 Inner 必须是静态的.
    

    内部类细节

    class Outer
    {
        int num = 3;
    
        class Inner
        {
            int num = 4;
    
            void show()
            {
                int num = 5;
                System.out.println(num); // 输出结果为 5
              // System.out.println(this.num); // 输出结果为: 4, 即内部类的 num
              // System.out.println(Outer.this.num); // 输出结果为 3, 即外部类的 num
            }
        }
    
        void method()
        {
            new Inner().show();
    }
    }
    
    class InnerClassDemo
    {
        public static void main(String[] args)
        {
            new Outer().method();
    }
    }
    

    局部内部类

    class Outer
    {
        int num = 3;
        void method()
        {
            final int x = 10;
            class Inner
            {
                void show()
                {
                    System.out.println("show..." + num); // 可以直接访问外部类局部变量
    
                    // 内部类在局部位置上只能访问局部中被 final 修饰的局部变量
                    System.out.println("run..." + x);
    
                }
            }
    
            Inner in = new Inner();
            in.show();
        }
    }
    
    class InnerClassDemo
    {
        public static void main(String[] args)
        {
            new Outer().method();
    }
    }
    

    匿名内部类

    前提: 内部类必须继承或着实现一个外部类或着接口
    匿名内部类, 其实就是一个匿名子类对象, 是内部类的简写格式.
    格式: new 父类 or 接口(){子类内容}

    abstract class Demo
    {
        abstract void show();
    }
    
    class Outer
    {
        int num = 4;
        /* 内部类有名字的情况
        class Inner extends Demo
        {
            void show()
            {
                System.out.println("show..." + num);
            }
        }
    
        public void method()
        {
            new Inner().show(); // 调用 show() 方法
        }
        */
    
        public void method()
        {
            new Demo() // 匿名内部类调用 show() 方法
            {
                void show()
                {
                    System.out.println("show......" + num);
                }
            }.show();
        }
    }
    

    匿名内部类应用

    当函数参数是接口类型时, 而且接口中的方法不超过三个,
    可以用匿名内部类作为实际参数进行传递.
    匿名内部类只能访问被 final 修饰的局部变量

    匿名内部类细节

    class Outer
    {
        void method()
        {
            new Object() // 匿名内部类
            {
                public void show()
                {
                    System.out.println("show run");
                }
            }.show(); // 此时调用完全没有问题
        }
    
        void function()
        {
            Object obj = new Object()
            {
                public void show()
                {
                    System.out.println("show run");
                }
            };
    
            obj.show(); // 编译失败, 因为匿名内部类这个子类对象被向上转型为了 Object  类型
                        // 这样就不能在使用子类特有方法了.
        }
    }
    



    _参考资料_ - [JavaSE 基础视频](https://www.bilibili.com/video/av3096713/#page=2) - [final 修饰的原因](https://www.zhihu.com/question/21395848) - [Java中匿名类的两种实现方式](http://blog.csdn.net/cntanghai/article/details/6094481)
  • 相关阅读:
    软件建模之UML图形讲解
    Android中级第八讲安卓子线程,以及定时任务使用讲解
    有你同行,我不会寂寞物联网操作系统Hello China后续开发计划及开发者征集
    物联网操作系统再思考Hello China操作系统的运营商网络协同机制
    Windows Phone 7 Storage
    Silverlight &Windows phone7 中使用Isolated Storage存储与读取图片
    Windows Phone7的Pivot控件简介
    windowsphone7的启动器和选择器
    如何将App的图标放到起始页面
    WebBrowser控件用法总结
  • 原文地址:https://www.cnblogs.com/linkworld/p/7445642.html
Copyright © 2011-2022 走看看