当前位置: 首页 > news >正文

【Java学习笔记】内部类(重点)

内部类(重点,难点,非常非常重要!!!

警告:此处为水平分水岭,务必理解透彻,即将对面向对象的理解上一个台阶!!!

注意:内部类是学习的难点,同时也是重点,后面看底层源码时,有大量的内部类!!!


1. 内部类的基本介绍

2. 内部类的分类

3. 对一些类概念的说明(关系见如下结构)

// 外部类
class outer_class{// 内部类class inner_class{}
}// 外部其他类(与外部类呈并列关系)
class other_outer_class{}

至此,类的所有内容完善了,形成一个完整的类结构!!!


一、局部内部类

1. 对于局部的理解

  • (1)既然是局部,说明特点就是在某一个结构中,并且是可以被调用的,调用后将会失效

  • (2)回顾类的五大结构,引出

    • 局部内部类定义于:类方法、代码块中

2. 对于局部内部类本质的理解

局部内部类的使用细节

代码解析

package inner;public class main {public static void main(String[] args) {System.out.println("你创建了外部类的一个对象,接下来是构造器的初始化\n");outer_class outer_class = new outer_class();System.out.println("接下来调用外部类的 test() 方法\n");outer_class.test();}
}// 外部类
class outer_class{{class inner_class_code_block{public void hi(){System.out.println("调用了 外部类 代码块中的 局部内部类 的 hi() 方法");}}inner_class_code_block inner_class_code_blockblock = new inner_class_code_block();inner_class_code_blockblock.hi();}int n1 = 10;private final int n2 = 20;// 构造器public outer_class(){// super()  调用父类的无参构造器,这里的父类是 Object()// 调用普通代码块// 类的属性初始化System.out.println("调用了 外部类 的 无参构造器\n");}public void test(){System.out.println("进入了外部类的 test() 方法\n");// 局部内部类class inner_class{final int n1 = 30;public void test(){System.out.println("进入了局部内部类的 test() 方法");System.out.println("1. 访问外部类的成员 n1= " + outer_class.this.n1 + "\n(访问方法:类名.this.n1;注意:当方法名重名的时候,遵循就近原则)" + "\n" );System.out.println("2. 访问外部类的 私有 成员 n2=" + n2 + "\n");System.out.println("3. 访问局部内部类的成员 n1=" + n1 + "\n");}}// 外部类想要访问内部类的成员或者方法:创建对象,然后访问inner_class inner_class = new inner_class();System.out.println("通过创建对象的方法\n\n一、外部类 调用 局部内部类的 成员 n1=" + inner_class.n1 + "\n");System.out.println("二、外部类 调用 局部内部类的 test()方法\n");inner_class.test();}
}// 输出结果
你创建了外部类的一个对象,接下来是构造器的初始化调用了 外部类 代码块中的 局部内部类 的 hi() 方法
调用了 外部类 的 无参构造器接下来调用外部类的 test() 方法
进入了外部类的 test() 方法通过创建对象的方法一、外部类 调用 局部内部类的 成员 n1=30二、外部类 调用 局部内部类的 test()方法进入了局部内部类的 test() 方法
1. 访问外部类的成员 n1= 10
(访问方法:类名.this.n1;注意:当方法名重名的时候,遵循就近原则)2. 访问外部类的 私有 成员 n2=203. 访问局部内部类的成员 n1=30

二、匿名内部类(重点)

为什么需要匿名内部类?

需求:创建一个类实现接口方法,然后再外部类中调用实现接口的方法

package anonymous;public class main {public static void main(String[] args) {outer_class outer_class = new outer_class();outer_class.test();}
}interface ia{public void run();
}// 单独创建tiger类,在outer_class中调用实现接口的方法
class tiger implements ia{public void run(){System.out.println("利用接口,实现了run()方法");}
}class outer_class{public void test(){tiger tiger = new tiger();System.out.println("在outer_class中调用tiger中的test()方法\n");tiger.run();}
}

如果要求该类只使用一次,代码存在的问题

引出—>匿名内部类

1. 基本介绍

2. 基本语法

new 类 或 接口(参数列表){类体
};

3. 匿名内部类的特点

匿名内部类即是一个类的定义,同时它本身也是一个对象,因此从语法上看,他既有定义类的特征,也有创建对象的特征,因此可以调用匿名内部类方法

4. 使用细节

>>提示:匿名内部类和局部内部类都是定义在局部位置上,具有的特性大同小异

package anonymous;public class main {public static void main(String[] args) {outer_class outer_class = new outer_class();outer_class.test();}
}interface ia{public void run();
}// 单独创建tiger类,在outer_class中调用实现接口的方法
class tiger implements ia{public void run(){System.out.println("利用接口,实现了run()方法");}
}class outer_class{public void test(){tiger tiger = new tiger();System.out.println("在outer_class中调用tiger中的test()方法\n");tiger.run();}
}

匿名内部类的使用场景

一、代码解析:基于接口的使用方法

package anonymous;public class main {public static void main(String[] args) {outer_class outer_class = new outer_class();outer_class.test();}
}interface ia{public void run();
}class outer_class{public void test(){ia tiger = new ia() {@Overridepublic void run() {System.out.println("在匿名内部类中,实现了接口方法run()");}};tiger.run();System.out.println("tiger的运行的运行类型是:" + tiger.getClass());}
}// 运行结果
在匿名内部类中,实现了接口方法run()
tiger的运行的运行类型是:class anonymous.outer_class$1

说明

class outer_class$1 implements ia{@Overridepublic void run() {System.out.println("在匿名内部类中,实现了接口方法run()");}
}

二、代码解析:基于类的使用方法

package anonymous;public class main {public static void main(String[] args) {outer_class outer_class = new outer_class();outer_class.test();}
}class father{String name;public father(){}public father(String name){this.name = name;}public void hi(){}}
class outer_class{public void test(){father father = new father() {@Overridepublic void hi(){System.out.println("匿名内部类重写了father类的hi()方法");}};father.hi();System.out.println("father的运行类型是:" + father.getClass());}
}
// 运行结果
匿名内部类重写了father类的hi()方法
father的运行类型是:class anonymous.outer_class$1

基于类匿名内部类的底层源码分析

class outer_class$1 extends father{@Overridepublic void hi(){System.out.println("匿名内部类重写了father类的hi()方法");}
}

三、基于抽象类的使用方法

package anonymous;public class main {public static void main(String[] args) {outer_class outer_class = new outer_class();outer_class.test();}
}abstract class A {public abstract void hi();
}class outer_class {public void test() {A a = new A() {@Overridepublic void hi(){System.out.println("匿名内部类中重写了抽象类中的hi()方法");}};a.hi();System.out.println("匿名内部类的运行类型是:" + a.getClass());}
}// 运行结果
匿名内部类中重写了抽象类中的hi()方法
匿名内部类的运行类型是:class anonymous.outer_class$1

基于抽象类的匿名内部类底层源码分析

class outer_class$1 extends A{@Overidepublic void hi(){System.out.println("匿名内部类中重写了抽象类中的hi()方法");}
}

四、匿名内部类的使用实例作为参数传递

要求:写一个类实现接口,在类中重写接口方法,在主类中调用接口方法

第一种:传统写法

package anonymous;public class main {public static void main(String[] args) {animal animal = new animal();tool.interface_implement(animal);}
}interface A{void hi();  // 默认是 public ,可以不写
}class animal implements A{@Overridepublic void hi() {System.out.println("animal类实现了接口,并重写了接口中的hi()方法");}
}class tool{public static void interface_implement(A interface_member){interface_member.hi();}
}// 运行结果
animal类实现了接口,并重写了接口中的hi()方法

问题分析:需要单独创建animal类实现接口,并重写接口中的方法,过于繁琐,代码冗余

第二种:匿名内部类

package anonymous;public class main {public static void main(String[] args) {tool.interface_implement(new A() {@Overridepublic void hi() {System.out.println("animal类实现了接口,并重写了接口中的hi()方法");}});}
}interface A{void hi();  // 默认是 public ,可以不写
}class tool{public static void interface_implement(A interface_member){interface_member.hi();}
}// 运行结果
animal类实现了接口,并重写了接口中的hi()方法

代码分析


总结:匿名内部类的本质可以理解为new 接口或类,在底层就会分配一个类(这个类就是匿名内部类)去实现接口或继承一个类返回这个类的对象实例地址,然后可以用一个对象实例接收,实现方法和成员的调用


三、成员内部类

1. 介绍:定义在外部类的成员位置,并且没有 static 修饰

2. 使用细节

3. 外部其他类访问成员内部类

  • 理解:首先成员内部类的本质是成员,即可以用通过对象去访问,然而访问的是一个类,需要创建对象实例

方法一:访问成员时创建对象实例

package anonymous;public class main {public static void main(String[] args) {other_class other_class = new other_class();other_class.hi();}
}class outer_class{class inner_class{public void hi(){System.out.println("调用了outer_class中inner_class的hi()方法");}}
}class other_class{// 在外部其他类中访问成员内部类public void hi(){System.out.println("调用了other_class的hi()方法");outer_class outer_class = new outer_class();// 访问成员的时候创建成员内部类对象实例outer_class.inner_class inner_class = outer_class.new inner_class();inner_class.hi();}
}// 输出结果
调用了other_class的hi()方法
调用了outer_class中inner_class的hi()方法

方法二:写一个方法返回对象实例

package anonymous;public class main {public static void main(String[] args) {other_class other_class = new other_class();other_class.hi();}
}class outer_class{class inner_class{public void hi(){System.out.println("调用了outer_class中inner_class的hi()方法");}}public inner_class get_inner_class_instance(){return new inner_class();}
}class other_class{// 在外部其他类中访问成员内部类public void hi(){System.out.println("调用了other_class的hi()方法");outer_class outer_class = new outer_class();// 访问成员的时候创建成员内部类对象实例outer_class.inner_class inner_class_instance = outer_class.get_inner_class_instance();inner_class_instance.hi();}
}// 输出结果
调用了other_class的hi()方法
调用了outer_class中inner_class的hi()方法

四、静态内部类

1. 介绍:静态内部类是定义在外部类的成员位置,并且有 static 修饰

2. 静态内部类的使用细节

提示:静态和普通的区别在于(1)静态只能访问静态的(2)普通的能访问静态和非静态的

3. 外部其他类访问静态内部类

方法一:类名访问静态内部类,创建对象实例

package anonymous;public class main {public static void main(String[] args) {other_class other_class = new other_class();other_class.hi();}
}class outer_class{static class inner_class{public void hi(){System.out.println("调用了outer_class中inner_class的hi()方法");}}
}class other_class{// 在外部其他类中访问成员内部类public void hi(){System.out.println("调用了other_class的hi()方法");// 注意:这里是静态内部类,直接通过类名访问outer_class.inner_class inner_class = new outer_class.inner_class();inner_class.hi();}
}// 输出结果
调用了other_class的hi()方法
调用了outer_class中inner_class的hi()方法

代码解析:由于是静态的,直接用通过类名访问到静态内部类,之后创建静态内部类对象实例,调用相关的方法即可

方法二:编写一个方法,可以返回静态内部类的对象实例

package anonymous;public class main {public static void main(String[] args) {other_class other_class = new other_class();other_class.hi();}
}class outer_class {static class inner_class {public void hi() {System.out.println("调用了outer_class中inner_class的hi()方法");}}public static outer_class.inner_class get_inner_class_instance() {return new outer_class.inner_class();}
}class other_class {// 在外部其他类中访问成员内部类public void hi() {System.out.println("调用了other_class的hi()方法");// 注意:这里是静态内部类,直接通过类名访问outer_class.inner_class inner_class_instance = outer_class.get_inner_class_instance();inner_class_instance.hi();}
}// 输出结果
调用了other_class的hi()方法
调用了outer_class中inner_class的hi()方法

代码解析:编写一个方法返回静态内部类实例对象,由于是静态的,直接通过外部类的类名访问静态内部类,用一个变量接收返回的静态内部类实例,通过对象调用相关的方法

http://www.xdnf.cn/news/742033.html

相关文章:

  • 数据结构:时间复杂度(Time Complexity)和空间复杂度(Space Complexity)
  • Typescript学习教程,从入门到精通,TypeScript 配置管理与编译器详解(19)
  • Rust 配置解析`serde` + `toml`
  • 华为OD机试真题——找出两个整数数组中同时出现的整数(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
  • 【HTML】基础学习【数据分析全栈攻略:爬虫+处理+可视化+报告】
  • MySQL事务与锁机制详解:确保数据一致性的关键【MySQL系列】
  • 005 flutter基础,初始文件讲解(4)
  • leetcode付费题 353. 贪吃蛇游戏解题思路
  • 实现MPC钱包
  • [蓝桥杯]阶乘求值【省模拟赛】
  • Thinkphp6实现websocket
  • Spring Boot养老院管理系统源码分享
  • MacOS安装Docker Desktop并汉化
  • 2.5 TypeScript 中的 instanceof 运算符
  • C++中全局变量和局部变量的区别
  • 华为OD机试真题——最小的调整次数/特异性双端队列(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
  • 【Netty系列】实现HTTP文件服务器
  • Redis:功能特性和应用场景
  • 学术合作交流
  • 生成https 证书步骤
  • 3D Gaussian splatting 04: 代码阅读-提取相机位姿和稀疏点云
  • 计算机网络物理层基础练习
  • 华为OD机试真题——硬件产品销售方案(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
  • 编辑器之神 Vim
  • python打卡第41天
  • Kafka ACK机制详解:数据可靠性与性能的权衡之道
  • AI炼丹日志-26 - crawl4ai 专为 AI 打造的爬虫爬取库 上手指南
  • Android之ListView
  • 第十二节:第三部分:集合框架:List系列集合:特点、方法、遍历方式、ArrayList集合的底层原理
  • 【Kotlin】数字字符串数组集合