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

【从0开始学习Java | 第12篇】内部类

在这里插入图片描述

文章目录

  • 基本介绍📖
    • 快速入门
    • 内部类的分类🧾
  • 局部内部类🥝
    • 说明⚠️
      • 为什么局部变量不能添加访问修饰符?🤔
    • 演示(注释非常重要)
  • 匿名内部类(最重要)🐦‍🔥
    • 说明(跟局部内部类类似)⚠️
    • 实例(注释非常重要)
    • 匿名内部类应用实践(当做实参传递,简洁高效)🍂
      • 案例1
      • 案例2
  • 成员内部类🥝
    • 说明⚠️
    • 示例
  • 静态内部类🥝
    • 说明⚠️
    • 示例

基本介绍📖

一个类的内部又完整的嵌套了另一个类结构,被嵌套的类称为内部类(inner class),嵌套了其他类的类称为外部类(outer class),使我们类的五大成员【属性、方法、构造器、代码块、内部类】,内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系。

快速入门

public class Learn{//外部其他类public static void main(String[] args){}
}class Outer{//外部类private int n1 =100; //属性public Outer(int n1) {//构造器this.n1 = n1;}public void m1(){//方法System.out.println("ma()");}{System.out.println("代码块....");}class Inner{ //内部类,在Outer类的内部}
}

内部类的分类🧾

定义在外部类的局部位置上(比如方法内):

  • 局部内部类(有类名)
  • 匿名内部类(没有类名,重点)

定义在外部类的成员位置上:

  • 成员内部类(没用static修饰)
  • 静态内部类(使用static修饰)

局部内部类🥝

说明⚠️

  1. 局部内部类是定义在外部类的局部位置,比如在方法中,并且有类名(本质仍然是一个类
  2. 可以直接访问外部类的所有成员,包含私有的
  3. 不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量不能使用访问修饰符,但是可以使用final修饰,因为局部变量也可以使用final
  4. 作用域:仅仅在定义它的方法或代码块中
  5. 局部内部类 - - -访问- - ->外部类的成员【访问方式:直接访问】
  6. 外部类 - - - 访问 - - ->局部内部类的成员
    访问方式:创建对象,再访问(注意:必须在作用域内)
  7. 外部其他类 - - - 不能访问 - - - >局部内部类(因为局部内部类地位是一个局部变量)
  8. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类.this.成员)去访问

为什么局部变量不能添加访问修饰符?🤔

原因:局部内部类的作用域被严格限制在其所在的代码块(如方法体)内部,就像方法中的局部变量一样。它的可见性仅局限于当前代码块,外部类的其他方法或外部类之外的代码都无法直接访问它。而访问修饰符的核心作用是控制跨作用域的访问权限(例如外部类访问内部类成员、子类继承时的可见性等)。对于局部内部类而言,由于其作用域已经被限定在局部代码块中,跨作用域访问本身就不存在,因此访问修饰符失去了实际意义

演示(注释非常重要)

public class Learn{//外部其他类public static void main(String[] args){new Outer().m1();}
}class Outer{//外部类private int n1 =100; //属性private void m2() {//私有方法System.out.println("m2()");}public void m1(){//方法//1.局部内部类是定义在外部类中的局部位置,通常在方法里面//3.不能添加访问修饰符,但是可以使用final修饰//4.作用域:仅仅在定义它的方法或代码块中final class Inner{ //局部内部类(本质仍然是一个类)private int n1=800;//2.可以直接访问外部类中的所有成员,包括私有的public void f1(){//6. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,//   如果想访问外部类的成员,则可以使用(外部类.this.成员)去访问System.out.println("n1="+n1+" 外部类的n1="+Outer.this.n1);m2();}}//5.外部类在方法中,可以创建Inner对象,然后调用方法即可Inner inner = new Inner();inner.f1();}
}

运行结果:

n1=800 外部类的n1=100
m2()

匿名内部类(最重要)🐦‍🔥

说明(跟局部内部类类似)⚠️

  1. 匿名内部类是定义在外部类的局部位置,如方法中,并且没有类名
  2. 匿名内部类的语法既有定义类的特征,也有创建对象的特征,因为匿名内部类既是一个类的定义,同时它本身也是一个对象
  3. 可以直接访问外部类的所有成员,包含私有的
  4. 不能添加访问修饰符,因为它是一个局部变量
  5. 作用域:仅仅在定义它的方法或代码块中
  6. 匿名内部类 - - - 访问 - - - > 外部类成员【直接访问】
  7. 外部其他类 - - - 不能访问 - - - >匿名内部类(局部变量)
  8. 如果外部类和匿名内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类.this.成员)去访问

基本语法

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

实例(注释非常重要)

public class AnonymousInnerClass {public static void main(String[] args){Outer04 outer04 = new Outer04();outer04.method();}
}interface IA {public void cry();
}class Outer04 {private int n1 = 10;public void method() {//基于接口的匿名内部类//1.需求:想使用接口IA,并创建对象//2.传统方式:写一个类,实现该接口,并创建该对象
//        IA tiger = new Tiger();
//        tiger.cry();//而需求是Tiger类是只使用一次,后面不再使用//4.可以使用匿名内部类来简化开发//6.tiger的编译类型是? IA//7.tiger的运行类型是?就是匿名内部类 ××× => Outer04$1/*
*       我们看底层: 会分配类名 Outer04$1
*       class ××× implement IA{
*           public voi cry() {
*               System.out.println("老虎叫唤");
*           }
*       }
*
* */// 8. jdk在底层创建匿名内部类 Outer04$1,立即就创建了Outer04$1实例,// 并把地址返回给tiger// 9.匿名内部类使用一次,就不能再使用(不是对象tiger)IA tiger = new IA(){public void cry(){System.out.println("老虎叫唤");}};tiger.cry();tiger.cry();System.out.println(tiger.getClass());//演示基于类的匿名内部类//分析//1. father编译类型 => Father//2. father运行类型 => Outer04$2//3. 底层会创建匿名内部类/**       class Outer04$2 extends Father{*           public void test(){System.out.println("匿名内部类重写了test方法");}*       }* */Father father = new Father("jack"){public void test(){System.out.println("匿名内部类重写了test方法");}};father.test();System.out.println("father对象的运行类型="+father.getClass());//基于抽象类的匿名内部类Animal animal = new Animal() {public void eat() {System.out.println("小狗吃骨头");}};animal.eat();System.out.println(animal.getClass());//也可以直接调用,不过只能使用一次//匿名内部类本身也是返回一个对象new Animal() {public void eat() {System.out.println("小猫吃猫粮");}}.eat();}}//class Tiger implements IA{
//    public void cry(){
//        System.out.println("老虎叫换");
//    }
//}class Father{public Father(String name){System.out.println("接收到了name="+name);}public void test(){}
}abstract class Animal{public abstract void eat();
}

运行结果:

老虎叫唤
老虎叫唤
class Outer04$1
接收到了name=jack
匿名内部类重写了test方法
father对象的运行类型=class Outer04$2
小狗吃骨头
class Outer04$3
小猫吃猫粮

匿名内部类应用实践(当做实参传递,简洁高效)🍂

案例1

public class Test {public static void main(String[] args){f1(new IB(){public void show(){System.out.println("show()");}});}public static void f1(IB ib){ib.show();}
}interface IB{public void show();
}

案例2

需求:

  1. 有一个铃声接口Bell,里面有一个ring方法
  2. 有一个手机类Cellphone,具有闹钟功能alarmclock,参数是Bell类型
  3. 测试手机类的闹钟功能,通过匿名内部类(对象)作为参数,打印:懒猪起床了
  4. 再传入另一个匿名内部类(对象),打印:小伙伴上课了
public class Test2 {public static void main(String[] args){Cellphone.alarmclock(new Bell(){public void ring(){System.out.println("懒猪起床了");}});Cellphone.alarmclock(new Bell(){public void ring(){System.out.println("小伙伴上课了");}});}
}interface Bell{public void ring();
}class Cellphone{public static void alarmclock(Bell bell){bell.ring(); //动态绑定}
}

输出:

n1 = 10 name = 张三
n1 = 10 name = 张三

成员内部类🥝

说明⚠️

  1. 成员内部类是定义在外部类的成员位置,并且没有static修饰(否则就是静态内部类了)

  2. 可以直接访问外部类的所有成员,包含私有的

  3. 可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员

  4. 成员内部类 - - - 访问 - - - > 外部类成员(比如:属性)【访问方式:直接访问】

  5. 外部类 - - - 访问 - - -> 成员内部类【访问方式:创建对象,再访问】

  6. 🧐外部其他类 - - - 访问 - - - > 成员内部类
    语法:Outer.Inner inner = new Outer.new Inner();

  7. 如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类.this.成员)去访问

示例

public class Test {public static void main(String[] args){Outer08 outer08  = new Outer08();outer08.t1();Outer08.Inner08 inner08 = new Outer08().new Inner08();inner08.say();}}class Outer08{//外部类private int n1=10;public String name = "张三";//注意:成员内部类,是定义在外部类的成员位置public class Inner08{//成员内部类public void say(){System.out.println("n1 = "+n1+" name = "+name);}}public void t1(){Inner08 inner08 = new Inner08();inner08.say();}
}

静态内部类🥝

说明⚠️

  1. 静态内部类是定义在外部类的成员位置,并且有static修饰
  2. 可以直接访问外部类的所有静态成员,但不能访问非静态成员👏
  3. 可以添加任意访问修饰符,因为它的地位就是一个成员
  4. 作用域:同其他成员,为整个类体
  5. 静态内部类 - - - 访问 - - - >外部类(比如:静态属性)【访问方式:直接访问所有静态成员】
  6. 外部类 - - - 访问 - - - > 静态内部类【访问方式:创建对象,再访问】
  7. 外部其他类 - - - 访问 - - - > 静态内部类
    语法之一:Outer.Inner inner = new Outer.Inner();
    inner.say();
  8. 如果外部类和静态内部类的成员重名时,静态内部类访问时,遵循就近原则,如果想访问外部类的静态成员,则可以使用(外部类.类名)去访问【这里没有this,因为只能访问外部类静态的静态成员】👏

示例

public class Test {public static void main(String[] args){new Outer10().m1();//静态内部类可以通过类名直接访问new Outer10.Inner10().say();}}class Outer10{//外部类private int n1=10;private static String name = "张三";static class Inner10{ //静态内部类public void say(){//只能访问外部类中的静态成员System.out.println(name);}}public void m1(){Inner10 inner10 = new Inner10();inner10.say();}
}

结果:

张三
张三

如果我的内容对你有帮助,请 点赞 评论 收藏 。创作不易,大家的支持就是我坚持下去的动力!
在这里插入图片描述

http://www.dtcms.com/a/310380.html

相关文章:

  • C语言:冒泡排序
  • VUE:学习路径
  • 机器学习:开启智能时代的钥匙
  • 前端学习日记(十七)
  • Unity3D制作UI动画效果
  • treeshaking,webpack,vite
  • 技术为核,口碑为盾:普瑞眼科成都市场“卷王”地位的形成逻辑
  • Canny边缘检测算法-个人记录
  • 计数组合学7.10(舒尔函数的组合定义)
  • 图片搜索1688的商品技术实现:API接口item_search_img
  • 嵌入式——C语言:俄罗斯方块
  • C#常见的转义字符
  • 国产开源大模型崛起:使用Kimi K2/Qwen2/GLM-4.5搭建编程助手
  • 浏览器渲染过程
  • VSCode Python 与 C++ 联合调试配置指南
  • web前端第一次作业
  • TwinCAT3编程入门2
  • 如何快速给PDF加书签--保姆级教程
  • TCP协议的特点和首部格式
  • 电力系统与变压器实验知识全总结 | 有功无功、同步发电机、短路空载实验、电压调整率、效率条件全讲透!
  • curl命令使用
  • 蒙特卡罗方法(Monte Carlo Method)_学习笔记
  • 【面板数据】全国31省名义、实际GDP及GDP平减指数数据(2000-2024年)
  • VR拍摄的流程与商业应用,实用的VR拍摄技巧
  • 汇川ITS7100E触摸屏交互界面开发(二)界面开发软件使用记录
  • python试卷01
  • Cesium性能优化
  • 代码随想录刷题Day22
  • 如何利用API接口与网页爬虫协同进行电商平台商品数据采集?
  • Java应用服务器选型指南:WebLogic vs. Tomcat、WebSphere、JBoss/Wildfly