Java学习笔记-day03-类名.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()方法,并没有。也可能是代码太长了没找到,或者版本比较新有改动。

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

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

相关文章

电子化以后如何申请软件著作权

​ 申请地址:中国版权登记业务平台 附件: 软件著作权设计说明书模板(含填写说明).docx 软件著作权源程序模板.docx 软件著作权前期开发说明、合作开发协议、版本说明、法人证明、授权书模板.docx 注册、登录和实名认证 首先访问…

系列十、Java中的八种基本数据类型

一、Java中的八种基本数据类型 1.1、概览 1.2、备注 byte最大值:127 ,byte最小值:-128 short最大值:32767 ,short最小值:-32768 int最大值:2147483647 ,int最小值:-2147483648 long最大值:9…

捕捉小红书开年顶流,品牌快“跟风”上车!

2024年开年,“南方小土豆”纷纷北上,元旦期间哈尔滨收入近60亿元,“冰雪”一跃成为今冬最炙手可热的流行趋势! 千瓜数据显示,小红书“冰雪”相关商业笔记同比去年增长649.84%。本期,千瓜将从“冰雪”场景出…

快速了解云计算与云原生

快速了解云计算与云原生 云计算云原生DevOps容器持续交付微服务 云计算 在讲云原生之前,先来讲讲云计算 其中云原生属于技术架构理念,而云计算提供应用所需的基础资源,云计算是云原生的基础,两者是相辅相成的 云计算简单来说&a…

高速PCB设计10大要点总结

学习高速PCB设计,掌握这10个知识点很重要! 在高速PCB设计的学习中,有很多的知识点需要大家去了解和掌握,比如常见的信号完整性、反射、串扰、电源噪声、滤波等。本文和大家分享10个和高速PCB设计相关的重要知识,希望对…

20240110-Python实现读取当前文件夹下所有视频名称和时长并生成一张表

代码 import os import cv2 import csv# 获取当前文件夹路径 folder_path os.getcwd() # 如果当前文件夹就是目标文件夹可以直接使用 ./,否则修改为目标文件夹的路径# 获取当前文件夹中所有视频文件的名称 video_files [f for f in os.listdir(folder_path) if …

尺寸链校核软件是什么?手机装配公差的含义是什么?让我们通过DTAS软件案例来解释。

尺寸公差软件 DTAS3D在智能手机装配过程中的应用非常重要,它能够帮助制造商提高产品质量和生产效率。这种软件可以帮助实现更高的装配精度,从而提升整体产品的质量。在这个案例中,DTAS3D的应用对于国产智能手机的装配过程起到了关键作用。 问…

JVM调优工具-VisualVM 远程连接服务器

通过windows系统中的VisualVM工具,监控Linux系统的测试环境或uat环境或生成环境,来监控JVM内存。 VisualVm提供在Java虚拟机(Java Virutal Machine,JVM)上运行的java应用程序。 只有按照了jdk,就可以在bi…

linux --proc文件夹学习笔记

内容在飞书文档: Docshttps://r0dhfl3ujy9.feishu.cn/docx/Xe2wd23MToSmGrxUm9kcVHrPn7g?fromfrom_copylink

Java后端返回的MySQL日期数据在前端格式错误的解决方法,区分jackson和fastjson

写在前面 在写web项目的时候经常会遇到后端返回的MySQL日期数据(date)类型在前端显示不正确的情况,有的时候会出现一串数字的时间戳,有的时候显示为日期晚了一天。 这是因Json给前端返回数据的时候格式问题造成的 解决方法 其实总结起来就是一句话在…

典型的无人机打击技术

无人机打击技术主要指的是用于中和、摧毁或干扰无人机(UAV)的各种技术手段。 这些技术随着无人机的广泛使用而迅速发展,特别是在军事和安全领域。下面是一些主要的无人机打击技术及其原理: 射频干扰(RF Jamming&#x…

统计学-R语言-1

文章目录 统计学介绍基本类型数据和变量数据抽样总结 统计学介绍 统计学(statistics)是“数据的科学” 1.是用以收集数据、分析数据和由数据得出结论的一组概念、原则和方法。 2.统计学进行推断的基础是数据(data)。数据不仅仅限于数字,也可能是图表、视频、音频或…