java内部类详解(IT枫斗者)

news/2024/10/21 7:57:29/

java-内部类详解

内部类概念

  • 定义:把类定义在其他类的内部,这个类被称为内部类(嵌套类)。
  • 分类:根据其所在位置及形式的不同,分为成员内部类、静态内部类、局部内部类、匿名内部类。

成员内部类

  • 联想到成员变量和成员方法,内部类所在位置和类的成员同级

  • // 外部类
    class OuterClass01 {// 成员内部类class InnerClass01 {}}
    
  • 观察一下生成的字节码文件,有两个:OuterClass01.class、OuterClass01KaTeX parse error: Expected 'EOF', got '&' at position 74: …so/search?q=外部类&̲spm=1001.2101.3…成员内部类名称.class。

创建方式:

  • 创建成员内部类对象的方式 1

  • 通过调用成员内部类的构造函数。

  • 格式:外部类名.内部类名 成员内部类对象名 = 外部类对象.new 内部类构造函数();

  • 方法1、OuterClass01.InnerClass01 innerClass01 = (new OuterClass01()).new InnerClass01();

  • 方法2、OuterClass01.InnerClass01 innerClass01 = new OuterClass01().new InnerClass01();

  • package cn.temptation;public class Test {public static void main(String[] args) {//创建出外部类对象OuterClass01 outerClass01 = new OuterClass01();OuterClass01.InnerClass01 innerClass01 = outerClass01.new InnerClass01();System.out.println(innerClass01);// cn.temptation.OuterClass01$InnerClass01@15db9742}}
    
  • 理解:OuterClass01.InnerClass01 innerClass01 = outerClass01.new InnerClass01();

  • 可以理解为:OuterClass01.InnerClass01 innerClass01 = outerClass01.(new InnerClass01());(这种写法语法有错,只是为了方便理解才这样写)即,通过对象名.这样的方式调用类的成员,这里的成员内部类也是这个外部类的成员,也就考虑使用对象名.这样的方式进行调用且这里要获取的是成员内部类对象,所以通过new 成员内部类的构造函数获取成员内部类对象

  • 创建成员内部类对象的方式2

  • 通过调用成员内部类所在的外部类的成员方法,在外部类中创建出成员内部类的对象

  • // 外部类
    class OuterClass02 {// 成员变量private InnerClass02 innerClass02;// 成员方法// 多例创建方法(在类的内部,成员方法可以访问成员)public InnerClass02 getInnerClass02() {return new InnerClass02();}// 单例创建方法(懒汉式,在类的内部,成员方法可以访问成员)public InnerClass02 getInstance() {if (innerClass02 == null) {innerClass02 = new InnerClass02();}return innerClass02;}// 成员内部类class InnerClass02 {// 设置构造函数为私有private InnerClass02() {}}}
    
  • package cn.temptation;public class Test {public static void main(String[] args) {OuterClass02 outerClass02 = new OuterClass02();// 创建成员内部类对象的写法(多例)OuterClass02.InnerClass02 innerClass02 = outerClass02.getInnerClass02();System.out.println(innerClass02);  //cn.temptation.OuterClass02$InnerClass02@15db9742OuterClass02.InnerClass02 innerClass02Ex = outerClass02.getInnerClass02();System.out.println(innerClass02Ex);  //cn.temptation.OuterClass02$InnerClass02@6d06d69cSystem.out.println("----------------------");// 创建成员内部类对象的写法(单例)OuterClass02.InnerClass02 innerClass02Demo = outerClass02.getInstance();System.out.println(innerClass02Demo);      //cn.temptation.OuterClass02$InnerClass02@7852e922OuterClass02.InnerClass02 innerClass02DemoEx = outerClass02.getInstance();System.out.println(innerClass02DemoEx);          //cn.temptation.OuterClass02$InnerClass02@7852e922}}
    

特点:

  • 成员内部类可以直接访问其所在的外部类的非静态成员变量和静态的成员变量

  • // 外部类class OuterClass04 {// 非静态的成员变量public int i = 2;private int j = 3;// 静态的成员变量public static int x = 4;private static int y = 5;// 成员内部类class InnerClass04 {// 成员方法public void showByInner() {// 成员内部类对于其所在的外部类的非静态成员变量均可以访问(不论使用public修饰,还是private修饰)System.out.println(i);System.out.println(j);// 成员内部类对于其所在的外部类的静态成员变量均可以访问(不论使用public修饰,还是private修饰)System.out.println(x);System.out.println(y);}}
    
  • 外部类和内部类成员变量相同时: 获取的变量值采取的是就近原则

  • // 外部类class OuterClass05 {// 非静态的成员变量public int i = 2;// 外部类的成员变量和内部类的成员变量同名public int k = 4;// 静态的成员变量public static int x = 6;public static int z = 8;// 成员内部类class InnerClass05 {// 非静态的成员变量public int j = 3;// 外部类的成员变量和内部类的成员变量同名public int k = 5;// 静态的成员变量:在非静态的成员内部类中定义静态的成员变量,语法出错// 语法错误:The field y cannot be declared static in a non-static inner type, unless initialized with a constant expression// public static int y = 7;// 语法错误:The field z cannot be declared static in a non-static inner type, unless initialized with a constant expression// public static int z = 9;// 成员方法public void showByInner() {System.out.println(i); // 2System.out.println(j); // 3System.out.println(k); // 5 --- 内部类的成员变量(就近原则)System.out.println(this.k); // 5 --- 内部类的成员变量(this指的是当前这个成员内部类对象)System.out.println(this); // cn.temptation.OuterClass05$InnerClass05@15db9742// 问题:就想在成员内部类的成员方法中使用其所在的外部类的同名成员变量,怎么办?// 思路1、考虑创建外部类对象,再通过外部类对象.成员变量获取System.out.println((new OuterClass05()).k); // 4 --- 外部类的成员变量// 思路2、考虑成员内部类对象创建出来时,其所在的外部类对象是否创建了,如果创建了,是什么样的访问形式// 答:创建了,访问形式为外部类类名.thisSystem.out.println(OuterClass05.this); // cn.temptation.OuterClass05@6d06d69cSystem.out.println(OuterClass05.this.k); // 4 --- 外部类的成员变量// 访问外部类的静态成员变量,直接通过外部类类名.静态成员变量System.out.println(OuterClass05.x); // 6System.out.println(OuterClass05.z); // 8}}
    
  • 成员内部类的成员方法可以访问其所在的外部类的所有成员方法(不论是否公有,不论是否静态)

  • // 外部类class OuterClass06 {// 成员方法public void method1() {System.out.println("外部类的公有非静态成员方法");}private void method2() {System.out.println("外部类的私有非静态成员方法");}public static void method3() {System.out.println("外部类的公有静态成员方法");}private static void method4() {System.out.println("外部类的私有静态成员方法");}// 成员内部类class InnerClass06 {// 成员方法public void showByInner() {// 成员内部类的成员方法可以访问其所在的外部类的所有成员方法(不论是否公有,不论是否静态)method1();method2();method3();method4();}}
    

静态内部类 (联想到静态成员,使用static修饰)

  • // 外部类class OuterClass08 {// 静态内部类static class InnerClass08 {}}
    
  • 观察一下生成的字节码文件,有两个:OuterClass08.class、OuterClass08 I n n e r C l a s s 08. c l a s s ,静态内部类字节码名称为:外部类名称 InnerClass08.class,静态内部类字节码名称为:外部类名称 InnerClass08.class,静态内部类字节码名称为:外部类名称静态内部类名称.class。

创建方式:

  • 格式:外部类名.内部类名 静态内部类对象名 = new 外部类名.静态内部类构造函数();

  • package cn.temptation;public class Test {public static void main(String[] args) {OuterClass08.InnerClass08 innerClass08 = new OuterClass08.InnerClass08();System.out.println(innerClass08);// cn.temptation.OuterClass08$InnerClass08@15db9742}}
    

特点:

  • 静态内部类中不论是静态的成员方法,还是非静态的成员方法,只能访问其所在的外部类的静态成员变量

  • // 外部类class OuterClass09 {// 非静态的成员变量public int i = 2;private int j = 3;// 静态的成员变量public static int x = 4;private static int y = 5;// 静态内部类static class InnerClass09 {// 非静态的成员方法public void showByInner() {// 静态内部类中的非静态成员方法无法访问其所在的外部类的非静态的成员变量// Cannot make a static reference to the non-static field i// System.out.println(i);// Cannot make a static reference to the non-static field j// System.out.println(j);// 静态内部类中的非静态成员方法可以访问其所在的外部类的静态的成员变量System.out.println(x); // 4System.out.println(y); // 5}// 静态的成员方法public static void showByInnerStatic() {// 静态内部类中的静态成员方法无法访问其所在的外部类的非静态的成员变量// Cannot make a static reference to the non-static field i// System.out.println(i);// Cannot make a static reference to the non-static field j// System.out.println(j);System.out.println(x); // 4System.out.println(y); // 5}}
    
  • 静态内部类中不论是静态的成员方法,还是非静态的成员方法,只能访问其所在的外部类的静态成员方法

  • // 外部类class OuterClass10 {// 成员方法public void method1() {System.out.println("外部类的公有非静态成员方法");}private void method2() {System.out.println("外部类的私有非静态成员方法");}public static void method3() {System.out.println("外部类的公有静态成员方法");}private static void method4() {System.out.println("外部类的私有静态成员方法");}// 静态内部类static class InnerClass10 {// 非静态的成员方法public void showByInner() {// 语法错误:Cannot make a static reference to the non-static method method1() from the type OuterClass10// method1();// 语法错误:Cannot make a static reference to the non-static method method2() from the type OuterClass10// method2();method3();method4();}// 静态的成员方法public static void showByInnerStatic() {// 语法错误:Cannot make a static reference to the non-static method method1() from the type OuterClass10// method1();// 语法错误:Cannot make a static reference to the non-static method method2() from the type OuterClass10// method2();method3();method4();}}
    

局部内部类(联想到局部变量,位于外部类的成员方法之中)

  • // 外部类class OuterClass12 {// 成员方法public Object showByOuter() {// 局部内部类class InnerClass12 {}// 在外部类的成员方法中实例化局部内部类InnerClass12 innerClass12 = new InnerClass12();return innerClass12;}}
    
  • 观察一下生成的字节码文件,有两个:OuterClass12.class、OuterClass12$1InnerClass12.class 局部内部类字节码名称为: 外部类名称 $ 编号 局部内部类名称.class。这里的编号是局部内部类类型的相应的编号,同一种局部内部类编号从1开始。

  • 注意:在同一个外部类的成员方法中,不允许创建多个同名的局部内部类;外部类中的不同成员方法中可以定义相同名称的局部内部类,这些局部内部类可以名称相同、成员不同。

  • 局部内部类的成员方法访问局部内部类所在的外部类的成员方法中定义的局部变量,局部变量可以使用final修饰,也可以不使用final修饰 ,但是不论是否使用final修饰,对于局部内部类的成员方法均只能访问(读取),而不能设置(赋值)

创建方式:

  • // 只能通过其所在的外部类的成员方法返回在成员方法中创建出的局部内部类对象
  • OuterClass12 outerClass12 = new OuterClass12();
  • System.out.println(outerClass12.showByOuter());

特点

  • 局部内部类中可以直接访问其所在的外部类的非静态的成员变量 和 静态的成员变量

  • // 外部类class OuterClass13 {// 非静态的成员变量public int i = 2;private int j = 3;// 外部类和局部内部类同名的成员变量public int k = 4;// 静态的成员变量public static int x = 6;private static int y = 7;public static int z = 8;// 成员方法public void showByOuter() {// 局部内部类class InnerClass13 {// 非静态的成员变量// 外部类和局部内部类同名的成员变量public int k = 5;// 静态的成员变量// 语法错误:The field z cannot be declared static in a non-static inner type, unless initialized with a constant expression// public static int z = 8;// 成员方法public void showByInner() {// 局部内部类对于其所在的外部类的非静态成员变量均可以访问(不论使用public修饰,还是private修饰)System.out.println(i); // 2System.out.println(j); // 3// 局部内部类对于其所在的外部类的静态成员变量均可以访问(不论使用public修饰,还是private修饰)System.out.println(x); // 6System.out.println(y); // 7System.out.println(k); // 5 --- 局部内部类的非静态成员变量(就近原则)System.out.println(this.k); // 5 --- 局部内部类的非静态成员变量(this指的是局部内部类对象)System.out.println(this); // cn.temptation.OuterClass13$1InnerClass13@15db9742System.out.println(OuterClass13.this); // cn.temptation.OuterClass13@6d06d69cSystem.out.println(OuterClass13.this.k); // 4 --- 外部类的非静态成员变量System.out.println(OuterClass13.z); // 8}}// 在外部类的成员方法中实例化局部内部类对象InnerClass13 innerClass13 = new InnerClass13();innerClass13.showByInner();}
    
  • 局部内部类中可以直接访问其所在的外部类的非静态的成员方法 和 静态的成员方法

  • // 外部类class OuterClass14 {// 成员方法public void method1() {System.out.println("外部类的公有非静态成员方法");}private void method2() {System.out.println("外部类的私有非静态成员方法");}public static void method3() {System.out.println("外部类的公有静态成员方法");}private static void method4() {System.out.println("外部类的私有静态成员方法");}public void showByOuter() {// 局部内部类class InnerClass14 {// 成员方法public void showByInner() {// 局部内部类对于其所在的外部类的非静态成员方法均可以访问(不论使用public修饰,还是private修饰)method1();method2();// 局部内部类对于其所在的外部类的静态成员方法均可以访问(不论使用public修饰,还是private修饰)method3();method4();}}// 在外部类的成员方法中实例化局部内部类对象InnerClass14 innerClass14 = new InnerClass14();innerClass14.showByInner();}
    

匿名内部类(联想到匿名对象和匿名数组,内部类没有名称,需要存在一个类或接口)

  • // 定义接口interface Foo {public abstract void show();}// 接口的实现类class FooImpl implements Foo {@Overridepublic void show() {System.out.println("接口的实现类的成员方法");}}// 外部类class OuterClass18 {// 成员方法public Foo showByOuter() {// 多态的写法,创建接口类型的变量,接收接口实现类类型的对象,并返回// Foo foo = new FooImpl();// return foo;// 对上述写法的变形,匿名对象的写法// return new FooImpl();// 实现了Foo接口的匿名内部类(位置位于类似局部内部类的位置)return new Foo() {@Overridepublic void show() {System.out.println("实现了接口的匿名内部类");}};}
    
  • 观察一下生成的字节码文件,有两个:OuterClass18.class、OuterClass18 1. c l a s s , 匿名内部类字节码名称为:外部类名称 1.class,匿名内部类字节码名称为: 外部类名称 1.class,匿名内部类字节码名称为:外部类名称编号.class

创建方式

  • 通过调用匿名内部类所在的外部类的成员方法

  • package cn.temptation;public class Test {public static void main(String[] args) {OuterClass18 outerClass18 = new OuterClass18();// 定义接口类型的变量来接收匿名内部类对象的返回Foo foo = outerClass18.showByOuter();System.out.println(foo);// cn.temptation.OuterClass18$1@15db9742foo.show(); // 这句语句实际调用接口实现对象(匿名内部类对象)的成员方法}}
    

特点

  • 匿名内部类没有构造函数,且使用者无法创建构造函数,但是实际上JDK为匿名内部类生成了构造函数

  • 匿名内部类的成员方法中可以访问其所在的外部类的成员变量(不论是否公有私有,不论是否静态非静态),变量相同时也是就近原则

  • // 接口interface Sample {public abstract void show();}// 外部类class OuterClass22 {// 成员变量public int i = 2;private int j = 3;int k = 6;public static int x = 4;private static int y = 5;// 成员方法public void showByOuter() {// 局部变量int k = 7;// 匿名内部类(new Sample() {@Overridepublic void show() {System.out.println(i); // 2System.out.println(j); // 3System.out.println(x); // 4System.out.println(y); // 5System.out.println(k); // 7 --- 局部变量(就近原则)// 语法错误:k cannot be resolved or is not a field// System.out.println(this.k);System.out.println(this); // cn.temptation.OuterClass22$1@15db9742System.out.println(OuterClass22.this); // cn.temptation.OuterClass22@6d06d69cSystem.out.println(OuterClass22.this.k);// 6}}).show();}
    

http://www.ppmy.cn/news/63956.html

相关文章

界面交互篇:答题页的答题逻辑交互开发

微信小程序云开发实战-答题积分赛小程序 界面交互篇:答题页的答题逻辑交互开发 前面的那一篇文章,我们已经完成了使用云开发的聚合能力实现从题库中随机抽取题目功能。 在页面加载时,实现从题库中随机抽取题目功能。那么,拿到数据后要干什么?如何做? 动态数据绑定 实…

android基础知识复习

架构: 应用框架层(Java API Framework)所提供的主要组件: 名称功能描述Activity Manager(活动管理器)管理各个应用程序生命周期,以及常用的导航回退功能Location Manager(位置管理器…

【tkinter 专栏】专栏前言

文章目录 前言本章内容导图1. tkinter 工具及特点2. 为什么使用 Python 进行 GUI 设计?2.1 Python 可以做什么2.2 使用 tkinter 可以干什么?3. 如何学习使用 tkinter 进行 GUI 设计?4. 开发环境搭建4.1 Python 的版本4.2 安装 Python4.2.1 下载 Python 安装包4.2.2 安装 Pyt…

【前端面试题】深拷贝的终极实现

大厂面试题分享 面试题库 前后端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 web前端面试题库 VS java后端面试题库大全 引子 通过本文可以学习到深拷贝的三种写法的实现思路与性能差异 首先,我们要理…

RK平台移植rtl8852bs wifi驱动

RK平台 android 12的内核里面没有rtl8852bs wifi驱动,找模组原厂要了驱动,看了一些是其他平台的。。。要放RK平台是编译不过的,要做一下相应的修改,巨坑! 首先,修改kernel-5.10/drivers/net/wireless/rockchip_wlan/Kconfig: --- a/kernel-5.10/drivers/net/wireless/r…

[光源频闪] Basler相机光源频闪设置操作说明

📢博客主页:https://loewen.blog.csdn.net📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢本文由 丶布布原创,首发于 CSDN,转载注明出处🙉📢现…

Java之多线程初阶2

目录 一.上节内容复习 1.进程和线程的区别 2.创建线程的四种方式 二.多线程的优点的代码展示 1.多线程的优点 2.代码实现 三.Thread类常用的方法 1.Thread类中的构造方法 2.Thread类中的属性 1.为线程命名并获取线程的名字 2.演示isDaemon() 3.演示isAlive() 4.演示…

BM61-矩阵最长递增路径

题目 给定一个 n 行 m 列矩阵 matrix ,矩阵内所有数均为非负整数。 你需要在矩阵中找到一条最长路径,使这条路径上的元素是递增的。并输出这条最长路径的长度。 这个路径必须满足以下条件: 对于每个单元格,你可以往上&#xff…