类名.this:内部类引用外部类实例

类名.this是啥意思?

今天在看尚硅谷的课程时里面讲了这么一句话:
集合在遍历时需要先创建一个容器,存放集合的数据,这样做浪费内存
想去验证下,就翻了翻ArrayList的迭代过程源码

ArrayList的迭代器类ItrArrayList的内部类)源码中有这么一段代码

Object[] elementData = ArrayList.this.elementData;

在这里插入图片描述

结论:

  1. 这行代码是Java中内部类(Inner Class)中的一种用法,通过类名.this来引用外部类的实例。

    在上述代码中,ArrayList.this表示在ArrayList的非静态内部类Itr中,引用外部的ArrayList实例的elementData属性。

  2. 在Java中,内部类有时候会引用外部类的实例。为了明确地表示使用的是外部类的实例而不是内部类的实例,可以使用外部类名.this的形式。

为什么内部类可以拿到外部类的实例?

结论

  • 成员内部类能够访问外部类的实例是因为编译器会在内部类中隐式地维护一个对外部类实例的引用。

解释

在 Java 中,内部类(Inner Class)可以访问其外部类(Enclosing Class)的实例,这是因为内部类被认为是外部类的一部分。这种访问的机制涉及到内部类的实现方式以及编译器的处理。

有两种主要的内部类:成员内部类(Member Inner Class)和静态内部类(Static Inner Class)。

  1. 成员内部类: 成员内部类是一个非静态的内部类,它隐含地持有对外部类实例的引用。当创建成员内部类的实例时,实际上会与外部类的实例关联起来。这就允许成员内部类访问外部类的实例变量和方法,同时也能够访问外部类的私有成员。

    public class OuterClass {private int outerVar;public class InnerClass {public void doSomething() {// 在内部类中可以访问外部类的实例变量outerVar = 10;}}
    }
    
  2. 静态内部类: 静态内部类是一个与外部类实例无关的内部类。它不隐含地持有对外部类实例的引用,因此在静态内部类中不能直接访问外部类的非静态成员。如果需要访问外部类的实例,必须通过外部类的对象来实现。

    public class OuterClass {private static int staticVar;public static class StaticInnerClass {public void doSomething() {// 在静态内部类中不能直接访问外部类的实例变量// 但可以访问外部类的静态变量staticVar = 20;}}
    }
    

总体而言,内部类能够访问外部类的实例是因为编译器会在内部类中隐式地维护一个对外部类实例的引用。这样的设计允许内部类更容易地与其外部类进行交互。

成员内部类中一定能获取到外部类实例吗?

结论

能,创建成员内部类实例需要通过外部类实例来创建

解释

在Java中,当创建内部类的实例时,通常是要先创建外部类的实例,然后通过这个外部类实例来创建内部类实例。因此,在访问外部类实例的情况下,通常可以假定外部类实例已经存在。

例如,对于成员内部类而言,它隐含地持有对外部类实例的引用,因此在创建成员内部类实例之前,通常需要有外部类的实例存在。

public class OuterClass {private int outerVar;public class InnerClass {public void doSomething() {// 在内部类中可以访问外部类的实例变量outerVar = 10;}}public static void main(String[] args) {OuterClass outerInstance = new OuterClass();OuterClass.InnerClass innerInstance = outerInstance.new InnerClass();innerInstance.doSomething();}
}

对于静态内部类,由于它不隐含地持有对外部类实例的引用,因此在创建静态内部类实例时,不需要先创建外部类的实例。静态内部类的创建方式如下:

public class OuterClass {private static int staticVar;public static class StaticInnerClass {public void doSomething() {// 在静态内部类中不能直接访问外部类的实例变量// 但可以访问外部类的静态变量staticVar = 20;}}public static void main(String[] args) {OuterClass.StaticInnerClass innerInstance = new OuterClass.StaticInnerClass();innerInstance.doSomething();}
}

总体而言,在使用内部类的情况下,通常会有外部类实例存在或者通过外部类实例来创建内部类实例。

成员内部类中修改外部类的实例的值,可以吗?

结论

可以(静态内部类中是不能的)

解释

在成员内部类中是可以修改外部类的实例的成员变量的。这是因为成员内部类会隐含地持有对外部类实例的引用。以下是一个示例:

public class OuterClass {private int outerVar;public class InnerClass {public void modifyOuterVar(int newValue) {// 在内部类中修改外部类的实例变量outerVar = newValue;}}public static void main(String[] args) {OuterClass outerInstance = new OuterClass();OuterClass.InnerClass innerInstance = outerInstance.new InnerClass();System.out.println("Before modification: " + outerInstance.outerVar);// 调用内部类的方法来修改外部类的实例变量innerInstance.modifyOuterVar(42);System.out.println("After modification: " + outerInstance.outerVar);}
}

在上述例子中,InnerClass 中的 modifyOuterVar 方法可以修改外部类 OuterClassouterVar 变量。

请注意,在静态内部类中是不能直接修改外部类的实例变量的,因为静态内部类没有隐含地持有对外部类实例的引用。如果需要在静态内部类中修改外部类的实例变量,需要通过外部类的实例来进行。

回到最初的问题,显然,集合在遍历时需要先创建一个容器是不正确的
ArrayList在迭代时直接通过成员内部类就可以直接访问到外部类实例数据ArrayList.this.elementData,通过它加上游标即可直接获取集合数据,实现遍历操作
猜想:
Fail-Fast机制的集合迭代的时候是不会创建新容器的。也是直接取原集合中的数据。
Fail-Safe机制的并发集合迭代的时候,可能也不需要创建新容器。
比较多的说法是并发集合会创建一个新的集合副本,再迭代,这样才能实现Fail-Safe,但是我看ConcurrentHashMap的keys()方法,并没有。也可能是代码太长了没找到,或者版本比较新有改动。

学习打卡:Java学习笔记-day03-类名.this:内部类引用外部类实例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/341538.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue过滤器详解

聚沙成塔每天进步一点点 本文内容 ⭐ 专栏简介基本用法多个过滤器的串联过滤器在指令中的应用全局过滤器 ⭐ 本期推荐 ⭐ 专栏简介 Vue学习之旅的奇妙世界 欢迎大家来到 Vue 技能树参考资料专栏!创建这个专栏的初衷是为了帮助大家更好地应对 Vue.js 技能树的学习。每…

螺纹钢负公差轧制中的测径仪应用

1、负公差轧制意义 为了满足生产使用要求,并根据轧制水平,在产品标准冲规定钢材尺寸的波动范围,允许钢材的实际尺寸与公称尺之间有一定的偏差,这个偏差一般称公差,公差分正、负公差,钢材按负公差轧制时&…

selenium不自动关闭chrome,selenium hello world

selenium不自动关闭chrome 用visual studio的话,右键,在终端运行。 from selenium import webdriveroptions webdriver.ChromeOptions() options.add_experimental_option("detach", True) driver webdriver.Chrome(optionsoptions) url …

详细分析Java中的分布式任务调度框架 XXL-Job

目录 前言1. 基本知识2. Demo3. 实战 前言 可视化任务调度 可视化配置 1. 基本知识 在Java中,分布式任务调度框架 XXL-Job 是一个开源的分布式任务调度平台,用于实现分布式系统中的定时任务调度和分布式任务执行。 下面是关于XXL-Job的一些概念、功…

Element-ui图片懒加载

核心代码 <el-image src"https://img-blog.csdnimg.cn/direct/2236deb5c315474884599d90a85d761d.png" alt"我是图片" lazy><img slot"error" src"https://img-blog.csdnimg.cn/direct/81bf096a0dff4e5fa58e5f43fd44dcc6.png&quo…

如何构建Prompt,帮我生成QA,作为召回率检索的测试集?

最近在做搜索召回率的提升工作。粮草未动兵马先行&#xff01;在做之前应该先有一把尺子来衡量召回率的好坏。所以应该先构建测试数据集&#xff0c;然后去做标准化测试。 有了测试机集以后。再去做搜索优化&#xff0c;才能看出来效果。 当然可以选择一些开源的测试集。如果可…

Github搭建图床 github搭建静态资源库 免费CDN加速 github搭建图床使用 jsdelivr CDN免费加速访问

Github搭建图床 github搭建静态资源库 免费CDN加速 github搭建图床使用 jsdelivr CDN免费加速访问 前言1、创建仓库2、开启 gh-pages页面功能3、访问测试 前言 写博客文章时&#xff0c;图片的上传和存放是一个问题&#xff0c;使用小众第三方图床&#xff0c;怕不稳定和倒闭&…

流程控制详解

1、Java流程控制 主要涉及三大流程控制&#xff1a;顺序、分支、循环 如下图&#xff1a; 1&#xff09;流程2 存在对用户名和密码的校验&#xff0c;是否为空&#xff0c;存在分支控制 2&#xff09;流程3 用户名和密码在数据库是否存在&#xff0c;存在分支控制 3&#xf…

VS中动态库的创建和调用

VS中动态库的创建和调用 库 ​ 库是写好的现有的&#xff0c;成熟的&#xff0c;可以复用的代码。库的存在形式本质上来说库是一种可执行代码的二进制。 ​ 库有两种&#xff1a;静态库&#xff08;.a、.lib&#xff09;和动态库&#xff08;.so、.dll&#xff09;。所谓静态…

使用 Docker 和 Diffusers 快速上手 Stable Video Diffusion 图生视频大模型

本篇文章聊聊&#xff0c;如何快速上手 Stable Video Diffusion (SVD) 图生视频大模型。 写在前面 月底计划在机器之心的“AI技术论坛”做关于使用开源模型 “Stable Diffusion 模型” 做有趣视频的实战分享。 因为会议分享时间有限&#xff0c;和之前一样&#xff0c;比较简…

Nginx配置反向代理实例二

Mac 安装Nginx教程 Nginx配置反向代理实例一 提醒一下&#xff1a;下面实例讲解是在Mac系统演示的&#xff1b; 反向代理实例二实现的效果 使用nginx 反向代理&#xff0c;根据访问的地址跳转到不同端口的服务中 nginx 监听端口为81&#xff1b; 访问地址1&#xff1a;http:/…

【高等数学之不定积分】

一、什么是不定积分? 我们可以简单地从英文层面来基础剖析一下&#xff0c;什么是不定积分? 1.1、基本概念 小tips: 二、不定积分运算法则 三、常用积分公式 四、第一类换元积分法 4.1、定义 4.2、常用凑微分公式 4.3、小calculate 五、第二类换元积分法 5.1、定义 …