Java:内部类

目录

  • 1.内部类介绍
  • 2.实例内部类
  • 3.静态内部类
  • 4.局部内部类
  • 5.匿名内部类

1.内部类介绍

当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么这个内部的完整结构最好使用内部类。在 Java 中,**可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类。**内部类也是封装的一种体现。
注意事项
1.定义在class 类名{}花括号外部的,即使是在一个文件里,都不能称为内部类,举例如下

public class A{  
}
class B{ 
}
// A 和 B是两个独立的类,彼此之前没有关系

2.内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件。如下说示:

class OuterClass{
    public int data1=1;
    private int data2=2;
    class InnerClass{
        public int data1=100;
        public int data3=3;

    }
}
public class Test {
    public static void main(String[] args) {
        OuterClass out=new OuterClass();
        OuterClass.InnerClass innerClass=out.new InnerClass();
    }
}

编译后产生的字节码文件
在这里插入图片描述

2.实例内部类

代码形式

class OuterClass{
    public int data1=1;
    private int data2=2;
    class InnerClass{
        public int data1=100;
        public int data3=3;
    }
}

1.外部类中的任何成员都可以在实例内部类方法中直接访问

class OuterClass{
    public int data1=1;
    private int data2=2;
    public void test(){
        System.out.println("OuterClass::test()");
        System.out.println(data1);    
    }
    class InnerClass{
        public void test1(){
            System.out.println("InnerClass::test()");
            System.out.println(data1);
            System.out.println(data2);
            //直接调用外部类的data1和data2并打印
        }
    }
}
public class Test {
    public static void main(String[] args) {
        OuterClass out=new OuterClass();
        OuterClass.InnerClass innerClass=out.new InnerClass();
        innerClass.test1();
    }
}

运行结果
在这里插入图片描述

2.实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束
在这里插入图片描述
使用private修饰后,下面实例化的时候就会报错,如下所示
在这里插入图片描述
被public修饰就不展示了
3.在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名称.this.同名成员 来访问

class OuterClass{
    public int data1=1;
    private int data2=2;
    public void test(){
        System.out.println("OuterClass::test()");
        System.out.println(data1);
    }
    class InnerClass{
        public int data1=100;//与外部类同名成员
        public void test1(){
            System.out.println("InnerClass::test()");
            System.out.println(this.data1);
            System.out.println(data2);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        OuterClass out=new OuterClass();
        OuterClass.InnerClass innerClass=out.new InnerClass();
        innerClass.test1();
    }
}

运行结果
在这里插入图片描述
如果要想访问到外部类的同名方法,修改如下

public void test1(){
            System.out.println("InnerClass::test()");
            System.out.println(OuterClass.this.data1);
            System.out.println(data2);
        }

运行结果
在这里插入图片描述

4.实例内部类对象必须在先有外部类对象前提下才能创建
下面提供两种实例化方式

public static void main(String[] args) {
// 要访问实例内部类中成员,必须要创建实例内部类的对象
// 而普通内部类定义与外部类成员定义位置相同,因此创建实例内部类对象时必须借助外部类
        OuterClass out=new OuterClass();
        OuterClass.InnerClass innerClass=out.new InnerClass();
        OuterClass.InnerClass innerClass1=new OuterClass().new InnerClass();
    }

5.实例内部类的非静态方法中包含了一个指向外部类对象的引用

class OuterClass{
    public int data1=1;
    private int data2=2;
    public void test(){
        System.out.println("OuterClass::test()");
        System.out.println(data1);
    }
    class InnerClass{

        public void test1(){
            OuterClass out=new OuterClass();
  //在内部类方法中创建一个外部类对象,通过这个对象调用外部类成员方法
            out.test();
            System.out.println("=================");
            System.out.println("InnerClass::test()");
            System.out.println(data1);
            System.out.println(data2);
        }

    }
}
public class Test {
    public static void main(String[] args) {
        OuterClass out=new OuterClass();
        OuterClass.InnerClass innerClass=out.new InnerClass();
        innerClass.test1();
    }
}

运行结果
在这里插入图片描述

6.外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。

class OuterClass{
    public int data1=1;
    private int data2=2;
    public void test(){
        OuterClass.InnerClass innerClass=new InnerClass();
        //在外部类中实例化了一个内部类对象调用内部类成员
        innerClass.test1();
        System.out.println("===================");
        System.out.println("OuterClass::test()");
        System.out.println(data1);
    }
    class InnerClass{
        public void test1(){
            System.out.println("InnerClass::test()");
            System.out.println(data1);
            System.out.println(data2);
        }

    }
}
public class Test {
    public static void main(String[] args) {
        OuterClass out=new OuterClass();
        out.test();
    }
}

运行结果
在这里插入图片描述

3.静态内部类

1.在静态内部类中只能访问外部类中的静态成员

class OuterClass{
    public int data1=1;
    private int data2=2;
    static int data3=3;
    public void test(){
        System.out.println("OuterClass::test()");
        System.out.println(data1);
    }
    static class InnerClass{
        public void test1(){
            System.out.println("InnerClass::test()");
            System.out.println(data1);//非静态成员,会报错
            System.out.println(data2);//非静态成员,会报错
            System.out.println(data3);//静态成员正常访问
        }
    }
}

在这里插入图片描述
如果确实想访问,我们该如何做?
在内部类方法里实例化一个外部类方法

static class InnerClass{
        public void test1(){
            OuterClass out=new OuterClass();
            System.out.println("InnerClass::test()");
            System.out.println(out.data1);
            System.out.println(out.data2);
            System.out.println(data3);
        }

运行结果
在这里插入图片描述
2.创建静态内部类对象时,不需要先创建外部类对象

public class Test {
    public static void main(String[] args) {
        OuterClass.InnerClass innerClass=new OuterClass.InnerClass();
        //直接通过外部类调用就可创建静态内部类的对象
        innerClass.test1();
    }
}

4.局部内部类

定义在外部类的方法体或者{}中,该种内部类只能在其定义的位置使用,一般使用的非常少,此处简单了解下语法格式。
1.局部内部类只能在所定义的方法体内部使用

class OuterClass{
    public void method() {
        int data1=1;
        class InnerClass{
            void test1(){
                System.out.println("InnerClass::test1()");
                System.out.println(data1);
            }
        }
        //只能在方法体内部使用
        InnerClass innerClass=new InnerClass();
        innerClass.test1();
    }
}
public class Test {
    public static void main(String[] args) {
        OuterClass out=new OuterClass();
        out.method();
    }
}

运行结果
在这里插入图片描述
如果在方法题外部使用会出现报错
在这里插入图片描述

2.不能被public、static等修饰符修饰
报错结果如下
在这里插入图片描述
在这里插入图片描述

3.编译器也有自己独立的字节码文件,命名格式:外部类名字$数字内部类名字.class
在这里插入图片描述
4.几乎不会使用

5.匿名内部类

匿名内部类可以用来实现一个接口并创建一个新的线程,举例如下

interface ITestable{
    void test();
}
public class Test {
    public static void main(String[] args) {
        new ITestable(){//直接实现这个接口
            @Override
            public void test() {
                System.out.println("hello zzuli");
            }
        };
    }
}

上面的代码相当于下面通过implments来实现一个接口

interface ITestable{
    void test();
}
class A implements ITestable{

    @Override
    public void test() {
        System.out.println("hello zzuli");
    }
}
public class Test {
    public static void main(String[] args) {
        A a=new A();
    }
    
}

我们通过匿名内部类来实现接口,那么我们应该怎么使用接口里的方法呢?
下面提供两种方法
方法一:直接通过.来调用,代码如下

interface ITestable{
    void test();
}
public class Test {
    public static void main(String[] args) {
        new ITestable(){
            @Override
            public void test() {
                System.out.println("hello zzuli");
            }
        }.test();//直接调用
    }
}

方法二:通过创建一个变量来调用(推荐使用)

interface ITestable{
    void test();
}
public class Test {
    public static void main(String[] args) {
        ITestable I=new ITestable(){
            @Override
            public void test() {
                System.out.println("hello zzuli");
            }
        };
        I.test();//通过变量名调用
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

KDD‘23 | AlphaMix: 高效专家混合框架(MoE)显著提高上证50选股表现

KDD23 | AlphaMix: 高效专家混合框架(MoE)显著提高上证50选股表现 原创 QuantML QuantML 2024-04-18 09:17 上海 Content 本文提出了一个名为AlphaMix的新型三阶段专家混合(Mixture-of-Experts,MoE)框架,…

信息流广告大行其是,微博回望“原生”的初心

摘要:有流量的地方,就当有原生信息流广告 信息流广告,自2006年Facebook推出后就迅速火遍全球数字营销界,被誉为实现了广告主、用户、媒体平台三赢。特别是随着OCPM/OCPX大放异彩,信息流广告几乎成为广告主的必选项&…

达梦数据库的AWR报告

达梦数据库的AWR报告 数据库快照是一个只读的静态的数据库。 DM 快照功能是基于数据库实现的,每个快照是基于数据库的只读镜像。通过检索快照,可以获取源数据库在快照创建时间点的相关数据信息。 为了方便管理自动工作集负载信息库 AWR(Auto…

数据结构实验(二)

单链表的基本操作 一、总的设计思路(c++实现) 1、首先定义一个包含name、gender、student_number、hobbies的学生信息结构体。 2、接着一一写出:链表初始化(initialize)函数、后插法插入(insert)函数、打印信息(output)函数、对链表结点进行排序(sortList)函数、…

【Qt 学习笔记】Qt常用控件 | 按钮类控件 | Check Box的使用及说明

博客主页:Duck Bro 博客主页系列专栏:Qt 专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ Qt常用控件 | 按钮类控件 | Check Box的使用及说明 文章编号&#xff…

华为ensp中MSTP多网段传输协议(原理及配置命令)

作者主页:点击! ENSP专栏:点击! 创作时间:2024年4月22日15点29分 在华为ENSP中,MSTP(多段传输协议)是重要的生成树协议,它扩展了STP(生成树协议&#xff09…

跨境电商日报:Tk使用时长全美第一;Shopee发布Z世代购物调查报告

# 平台资讯 PART 1 电商 Shopee调查:六成Z世代购物者看重平台功能多样性 日前,据外媒报道,Shopee发布了《在数字时代吸引Z世代购物者》调查报告。数据显示,60%的Z世代购物者优先考虑搜索简单、具有比较功能和有用评论的平台。据…

代码随想录算法训练营第三十六天|435. 无重叠区间,763.划分字母区间,56. 合并区间

题目:435. 无重叠区间 给定一个区间的集合 intervals ,其中 intervals[i] [starti, endi]。返回需要移除区间的最小数量,使剩余区间互不重叠。 题目链接/讲解链接: https://programmercarl.com/0435.%E6%97%A0%E9%87%8D%E5%8F%A0…

Swin Transformer 浅析

Swin Transformer 浅析 文章目录 Swin Transformer 浅析引言Swin Transformer 的网络结构W-MSA 窗口多头注意力机制SW-MSA 滑动窗口多头注意力机制Patch Merging 图块合并 引言 因为ViT无法实现CNN中的层次化构建以及局部信息,由此微软团队提出了Swin Transformer来…

Linux磁盘及读写数据原理/Raid技术/硬软raid及企业案例/磁盘分区环境搭建/格式化磁盘系列-12213字

高薪思维: 怎么才能一直去坚持下去? 1.做这件事情的好处,对自己一直去放大。 2.不做的坏处,并放大 3.学习痛苦?还是去上班(餐饮、外卖痛苦?) 用比学习更痛苦的事情,去对抗…

Java后端中如何随意接收参数

目录 一、参数名相同 二、参数名不同,使用RequestParam注解 大概访问流程是:先访问test控制器,test控制器跳转到index页面(此时index页面收到了test控制器传来的数据),然后在index页面跳转到t5控制器&…

【YOLOv9】实战二:手把手教你使用TensorRT实现YOLOv9实时目标检测(含源码)

‍‍🏡博客主页: virobotics(仪酷智能):LabVIEW深度学习、人工智能博主 🎄所属专栏:『LabVIEW深度学习实战』 📑上期文章:『【YOLOv9】实战一:在 Windows 上使用LabVIEW OpenVINO工具…

Java代码基础算法练习-分段函数求值-2024.04.21

任务描述: 有一个函数,写一段程序,输入x,输出y。 任务要求: 代码示例: package April_2024;import java.util.Scanner;public class a240421 {public static void main(String[] args) {Scanner sc new S…

Print Conductor 文档批量打印工具 v9.0.2312

网盘下载 Print Conductor 是 Windows 上一款功能强大的文档批量打印工具,通过该软件可以快速的帮用户批量处理打印PDF文件、协议、文档、图纸、演示文稿、文本文件等,完美的支持PDF、DOC、JPG、PNG、SNP、PSD、MSG、WRI、WPS、RTF、TXT、XLS、PPT、PPS、…

spring高级篇(三)

1、Spring选择代理 1.1、Aspect和Advisor 在Spring框架中,"Aspect" 和 "Advisor" 是两个关键的概念,它们都与AOP(面向切面编程)密切相关: 如果要在Spring中定义一个Aop类,通常会&…

山与路远程控制 一个基于electron和golang实现的远控软件

山与路远程控制 🎥项目演示地址 还在制作… ♻️项目基本介绍 山与路远程控制是基于electron(vue3)和golang实现的远程控制软件(项目界面主要模仿向日葵远程软件,如有侵权请告知),代码可能有点臃肿毕竟只花了一周左右写的无聊项目,如果对其感兴趣的大佬可以fork自…

【Qt 学习笔记】Qt常用控件 | 显示类控件 | Label的使用及说明

博客主页:Duck Bro 博客主页系列专栏:Qt 专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ Qt常用控件 | 显示类控件 | Label的使用及说明 文章编号:Q…

根据表格该列数据的长度动态变化该列的宽度;

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、代码前言 在使用elementui的表格将数据展示出来时,我们想根据表格该列数据的长度动态变化该列的宽度; 1.看了一下elementui文档有一个 width 的属性,可用它来修改对应列。 2.那么我们需要拿到该列的所有数据去比较…

Go栈内存管理源码解读

基本介绍 栈内存一般是由Go编译器自动分配和释放,其中存储着函数的入参和局部变量,这些参数和变量随着函数调用而创建,当调用结束后也会随之被回收。通常开发者不需要关注内存是分配在堆上还是栈上,这部分由编译器在编译阶段通过…