内部类

🐓内部类

可以将一个类定义在另一个类或方法中,这样的类称为内部类

将类定义在另一个类中成员的位置

public class Inner {
    // 定义在类内部
    class Demo{
        public void say(){
            System.out.println("hello!");
        }
    }
}

成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)

成员内部类依赖于外部类, 要创建内部类的对象, 先要创建外部类的对象

public class Inner {
    private static final String name ="张三";
    public static void say(){
        System.out.println("我是外部类方法!");
    }

    class Demo{
        public void go(){
            // 调用外部类方法及变量
            System.out.println(name);
            Inner.say();
        }
    }
}

/*
    测试
*/
@Test
public void test1(){
    // 先创建外部类实例
    Inner.Demo demo = new Inner().new Demo();
    demo.go();
}

外部类访问内部类时,必须要先实例化内部类的对象

public class Inner {

    public void go(){
        // 实例化内部类
        new Demo().say();
    }

    class Demo{
        private final String name = "李四";
        public void say(){
            System.out.println("我是内部类方法!");
        }
    }
}

成员内部类可以拥有如成员方法般的多种修饰符

public class Inner {
    // public
    public class Demo{}
    // private
    private class Demo2{}
    // protected
    protected class Demo3{}
    // default
    class Demo4{}
}

当外部类和内部类拥有同名的成员变量和方法时,会发生隐藏现象,默认调用内部类的成员

使用外部类.this.变量 和 外部类.this.方法,指定使用外部类变量及方法

public class Inner {
    private String name = "张三";
    public void say(){
        System.out.println("外部类方法!");
    }

    class Demo{
        private String name = "李四";
        public void say(){
            System.out.println("内部类方法!");
        }
        public void go(){
            System.out.println(Inner.this.name);
            Inner.this.say();
        }
    }
}

将内定义在另一个类的方法中

public class Inner {
    public void method() {
        class Demo {
            public void say() {
                System.out.println("hello");
            }
        }
        // 在方法内部调用内部类
        new Demo().say();
    }
}

/*
    测试
*/
@Test
public void test1(){
    Inner inner = new Inner();
    inner.method();
}

局部内部类的访问权限仅限于方法内或者该作用域内

局部内部类和局部变量一样,不能有public, private, protected以及static修饰符

使用内部类能够在实现父类或者接口方法的同时, 产生一个对象

// 接口
public interface Demo{
    void say();
}

/*
    测试
*/

// 产生对象直接调用
@Test
public void test1(){
    Demo demo = new Demo() {
        @Override
        public void say() {
            System.out.println("匿名内部类!");
        }
    };
    demo.say();
}

匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候由系统自动起名为Outter$1.class。一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。

public class Inner {
    // 需要接口类型的参数
    public void go(Demo demo){
        demo.say();
    }
}

interface Demo{
    void say();
}

/*
    测试
*/
@Test
public void test1(){
    Inner inner = new Inner();
    // 匿名内部类
    inner.go(new Demo() {
        @Override
        public void say() {
            System.out.println("匿名内部类!");
        }
    });
}

和成员内部类的区别是, 静态内部类不依赖于外部类, 但是静态内部类不能调用外部类的非static成员变量或方法

public class Inner{
    private static final String name = "张三";
    // 无法调用非static方法
    private Integer age = 22;
    public static void say(){
        System.out.println("外部类方法!");
    }

    static class Demo{
        public void say(){
            System.out.println(name);
            Inner.say();
        }
    }
}

/*
    测试
*/
@Test
public void test1(){
    // 无依赖于外部类
    Inner.Demo demo = new Inner.Demo();
    demo.say();
}
  • 为什么成员内部类可以无条件访问外部类?
编译器会默认为成员内部类添加一个指向外部类对象的引用
虽然成员内部类的构造函数是空参的,但编译器仍会默认添加一个参数,类型是内部类指向外部类对象的引用类型,从而达到将引用传入的效果
  • JDK8之前, 使用局部内部类和匿名内部类访问的变量只能是final类型 为什么使用final修饰
会出现外部方法已经结束,而局部内部类还没有结束的情况,如果局部内部类需要外部方法的传参,而方法已经结束了,就会出现错误
所以编译器采用复制的方法,在编译期间变量字面值确定的情况下,在匿名内部类或局部方法的常量池中添加一个内容相同的字面量或直接键相应的字节码嵌入到执行字节码中,这样就可以和方法中局部变量分隔开
但是,如果修改方法中的局部变量,又该怎么办呢,所有要求局部内部类访问的变量只能是final类型,使字面量无法修改
  • 为什么使用内部类
1. 每个类都能独立继承一个父类,不管外部类是否继承了父类,使用多继承的解决方案变得完整
2. 方便将存在一定逻辑的类组织在一起,又实现对外的隐藏
3. 方便编写事件驱动
4. 方便编写线程代码
5. 简化代码,利于维护

Original: https://www.cnblogs.com/suwuji/p/16555779.html
Author: 苏无及
Title: 内部类

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/612798/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • MySQL8.0 新特性 Hash Join

    概述&背景 MySQL一直被人诟病没有实现HashJoin,最新发布的8.0.18已经带上了这个功能,令人欣喜。有时候在想,MySQL为什么一直不支持HashJoin呢?我…

    数据库 2023年6月9日
    093
  • 事务

    事务 *事务的简介 事务是一组操作的集合,这是一个不可分割的工作单元。事务将向整个系统提交或取消操作请求。这些操作只能同时成功和失败。 [En] A transaction is …

    数据库 2023年5月24日
    0114
  • MySQL事务提交流程详解

    一. 事务的提交流程。 获取 MDL_key::COMMIT 锁: FTWRL会阻塞 commit 操作。 XID_Event生成并写入binlog cache中。会首先将事务中的…

    数据库 2023年5月24日
    098
  • StoneDB(石原子科技)受邀参与《开源数据库服务商服务能力分级要求》标准第一次讨论会

    2022年8月9日下午,StoneDB数据库主体研发单位石原子科技与华为、openGauss开源社区、云和恩墨、甲骨文等组织受邀参与《开源数据库服务商服务能力分级要求》标准第一次讨…

    数据库 2023年5月24日
    074
  • 弱隔离级别 & 事务并发问题

    为什么要有弱隔离级别 如果两个事务操作的是不同的数据, 即不存在数据依赖关系, 则它们可以安全地并行执行。但是当出现某个事务修改数据而另一个事务同时要读取该数据, 或者两个事务同时…

    数据库 2023年6月11日
    080
  • 2022-8-17 mysql 第三天

    子查询 按照结果集的行列数不同,子查询可以分为以下几类: 标量子查询:结果集只有一行一列(单行子查询) 列子查询:结果集有一列多行 行子查询:结果集有一行多列 表子查询:结果集多行…

    数据库 2023年6月14日
    081
  • Rabbitmq从安装到简单入门

    1:Rabbitmq是什么? RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。 它由以高性能、健壮以及可伸缩性出名的 Erlang …

    数据库 2023年6月6日
    086
  • 今日🎸吉他练到这儿

    本文来自博客园,作者:ukyo–BlackJesus,转载请注明原文链接:https://www.cnblogs.com/ukzq/p/16750421.html Or…

    数据库 2023年6月11日
    0102
  • 实现一个简单的Database3(译文)

    前文回顾 实现一个简单的Database1(译文) 实现一个简单的Database2(译文) 实现一个简单的Database3(译文) 译注:cstsck在github维护了一个简…

    数据库 2023年6月11日
    095
  • VUE项目开发报错:Error in render: “TypeError: Cannot read property ‘country’ of undefined”

    VUE项目开发中遇到的问题记录一下 如题,vue页面开发中控制台报如上错误,但是页面展示是有数据的,展示正常,具体错误如下图 对页面展示没有影响,但是控制台一直报这个错,看着就不舒…

    数据库 2023年6月9日
    085
  • 代码更新提交到GIT

    1、先克隆代码到本地做备份(在需要克隆项目的的那个文件夹下使用Git Bash Here可以直接定位到当前目录,不让需要定位cd命令到目录再使用克隆命令) $ git clone …

    数据库 2023年6月11日
    0103
  • Docker下部署Spring Boot项目

    1.编写Docker File FROM openjdk:8-jdk-slim LABEL maintainer=ddzhan COPY target/*.jar /app.jar…

    数据库 2023年6月6日
    090
  • 几款ZooKeeper可视化工具,最后一个美炸了~

    首发于公众号:BiggerBoy欢迎关注,查看更多技术文章 ZooKeeper是我们工作中常用一个开源的分布式协调服务,提供分布式数据一致性解决方案,分布式应用程序可以实现数据发布…

    数据库 2023年6月11日
    099
  • navicat~导出数据库密码

    当我们mysql密码忘记了,而在navicat里有记录,我们应该如何导出这个密码呢? 第一步:文件菜单,导出链接,导出连接获取到 connections.ncx 文件 这里需要勾选…

    数据库 2023年5月24日
    0179
  • 数据库基本知识和MySQL

    数据库的基本知识和MySQL 数据库 数据库 (database) 指保存有组织的数据的容器,人们一般情况说的数据库指的是数据库软件,即数据库管理系统 (DBMS) ,而数据库实确…

    数据库 2023年6月16日
    0134
  • MySQL启动过程详解一:启动整体流程

    MySQL启动流程如下: 设置进程名 处理配置文件及启动参数以及部分模块初始化,这包括: 2.1 从配置文件中读取选项,把他们放在 argc 和 argv 已有的参数之前 2.2 …

    数据库 2023年6月9日
    068
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球