• Java内部类


    学Java,内部类,累不累?(冷笑话)

    目录

    一、内部类的理解

    二、四种内部类

    ①成员内部类

    1)定义方式

    2)成员内部类访问外部成员

    3)成员内部类实例化对象

    ②局部内部类

    ③静态内部类

    ④匿名内部类(重难)

    1)理解

    2)匿名内部类的形式

    3)匿名内部类的使用


    一、内部类的理解

    什么是内部类?我们对普通的类已经很理解了,比如人类(person)、动物类(animal)、书类(book),突然发现这些类似乎都比较广泛,或者说更贴近一个大的整体。如果一个整体的内部结构很复杂,比方说人类(person),你光说这个人叫什么名(name),今年几岁(age),是男是女(gender)……似乎都只是很概括性地描述人这个类,如果要把人类更细致的结构描述出来,作为人类你有五官、有五脏六腑、有骨骼、肌肉,不难发现,前面举例的这些“零件”似乎也能单独视作一个类,(比如)眼睛类->单双眼皮、眸色……

    因此,为了更细致地描述一个大的类,可以用内部类去描述这个大类中可以单独“拆分”出来的“零件”,这样既贴切我们的认知,又方便代码的维护

    二、四种内部类

    分别是:成员内部类、局部内部类、静态内部类、匿名内部类

    ①成员内部类

    1)定义方式

    在一个类中,我们已经熟知的,可以定义:成员变量、成员方法;

    如果在Outer类中定义一个Inner类,则称Inner是Outer的一个内部类相对的,可以称Outer是Inner的外部类

    代码示例:

    1. class Person {
    2. String name;
    3. int age;
    4. class Eye {
    5. String eyelid;//单双眼皮
    6. String Color;//眸色
    7. }
    8. }

    在这个示例中,Peron类拥有两个成员属性和一个成员内部类,name和age分别用来描述姓名和年龄,eyelid和Color分别用来描述单双眼皮和眸色,当然你完全可以把这两个属性直接作为Person类的成员属性,但如果采用内部类的形式书写->既贴切我们的认知,又方便代码的维护

    2)成员内部类访问外部成员

    成员内部类作为外部类的一个成员,自然是可以访问外部类的属性的,代码示例:

    1. class Person {
    2. String name = "张三";
    3. int age = 18;
    4. class Eye {
    5. String eyelid;//单双眼皮
    6. String Color;//眸色
    7. void print() {//定义一个print函数,作为Eye这个内部类的成员方法
    8. System.out.println(name + "今年" + age + "岁");
    9. //访问外部类的name和age两个属性
    10. }
    11. }
    12. }

    3)成员内部类实例化对象

    用成员内部类实例化对象的公式如下:

    外部类名.内部类名 变量名 = new 外部类名().new 内部类名();

    解释:

    等号左边,用外部类名.的形式访问到内部类名;

    等号右边,理解为->先用new 外部类名()实例化了一个外部类对象,然后用这个外部类对象.的形式访问到内部类名,此时再用这个内部类名去new一个内部类对象

    代码示例;

    1. public class Main {
    2. public static void main(String[] args) {
    3. //外部类名.内部类名 变量名 = new 外部类名().new 内部类名();
    4. Person.Eye e1 = new Person().new Eye();
    5. e1.print();
    6. }
    7. }
    8. class Person {
    9. String name = "张三";
    10. int age = 18;
    11. class Eye {
    12. String eyelid;//单双眼皮
    13. String Color;//眸色
    14. void print() {//定义一个print函数,作为Eye这个内部类的成员方法
    15. System.out.println(name + "今年" + age + "岁");
    16. }
    17. }
    18. }

    ②局部内部类

    局部内部类的定义和使用——

    局部内部类,也叫作方法内部类;

    在一个类的成员方法中定义一个内部类,这个类就属于局部内部类,因为它的作用范围(生命周期)只局限在这个类中;

    在局部内部类中,局部内部类可以访问外部类的所有成员变量和方法,而局部内部类中变量和方法却只能在所属方法中访问;

    1. public class Main {
    2. public static void main(String[] args) {
    3. #用Person实例化对象并调用它的成员方法func
    4. Person p = new Person();
    5. p.func();
    6. }
    7. }
    8. class Person {
    9. String name = "张三";
    10. int age = 18;
    11. void func() {
    12. class Eye {
    13. String eyelid;//单双眼皮
    14. String Color;//眸色
    15. void print() {//定义一个print函数,作为Eye这个内部类的成员方法
    16. System.out.println(name + "今年" + age + "岁");
    17. }
    18. }
    19. //局部内部类,只能在func里访问,因此在此处实例化内部类Eye对象e并调用print方法
    20. Eye e = new Eye();
    21. e.print();
    22. }
    23. }

    上述代码中,定义了一个Person类,在Person类中定义了一个成员方法func,在func方法中定义了一个内部类Eye,故称Eye是Person类的局部内部类,其中——

    Eye类可以访问外部类Person的所有成员,但Eye这个局部内部类的属性和方法只能在func这个方法里面访问!

    ③静态内部类

    1)静态内部类的特点

    在形式上,就只是在成员内部类的基础上加以static关键字修饰

    在功能上,

    ㈠静态内部类只能访问外部类的静态成员;

    ㈡访问静态内部类的成员时,可以跳过它的外部类

    2)静态内部类实例化对象

    用静态内部类实例化对象的公式如下:

    外部类名.内部类名 变量名 = new 外部类名.内部类名();

    解释:

    等号左边和成员内部类是一样的,不再赘述

    等号右边,我们知道类的静态成员是可以通过类名直接访问的,因此直接用外部类名.的形式可以访问到静态内部类,然后用这个静态内部类去new一个静态内部类对象

    示例用来理解以上两点:

    1. public class Main {
    2. public static void main(String[] args) {
    3. //外部类名.内部类名 变量名 = new 外部类名.内部类名();
    4. Person.Eye e = new Person.Eye();
    5. e.print();
    6. }
    7. }
    8. class Person {
    9. static String name = "张三";
    10. int age = 18;
    11. static class Eye {
    12. String eyelid;//单双眼皮
    13. String Color;//眸色
    14. void print() {
    15. System.out.println("姓名是" + name);//name是外部类的静态成员,可以正常访问
    16. //System.out.println("年龄是" + age);错误语法!静态内部类只能访问外部类的静态成员
    17. }
    18. }
    19. }

    匿名内部类(重难)

    1)理解

    所谓匿名,就是没有名字,匿名内部类,就是没有名字的内部类;

    我们经常会遇到一个对象只用一次的情况,这种情况下如果用匿名内部类,就可以不必创建新的子类去继承(extends)或实现(implements),然后才能用子类去实例化对象

    我个人的理解:直接把匿名类对象看作是一个具体的变量(已经被实例化好的具体对象)

    2)匿名内部类的形式

    匿名内部类有两种定义形式,㈠继承父类;㈡实现接口

    代码示例:

    1. interface Mouth {
    2. String test2 = "这是嘴类,我把它作为一个接口";
    3. void Mouth_print();
    4. }
    5. abstract class Eye {
    6. String test1 = "这是眼睛类,我把它作为一个父类";
    7. abstract void Eye_show();
    8. }
    9. public class Main {
    10. public static void main(String[] args) {
    11. new Eye() {//继承父类的匿名内部类
    12. @Override
    13. void Eye_show() {
    14. System.out.println("调用Eye父类的test成员属性:" + test1);
    15. }
    16. };
    17. new Mouth() {
    18. @Override
    19. public void Mouth_print() {
    20. System.out.println("调用Mouth接口的test成员属性" + test2);
    21. }
    22. };
    23. }
    24. }

    补充内容(进阶操作,可不看):

    ㈠找到字节码文件(.class)

    ㈡在当前目录打开命令行窗口(cmd)

    ㈢对两个字节码文件分别进行反编译

    ㈣得到反编译结果

    分析:显然Eye是我们定义的父类,而Mouth是定义的接口,因此内部类1隐藏的是extends关键字,内部类2隐藏的是implements关键字

    3)匿名内部类的使用

    对于一个匿名内部类,可以直接把它视作成一个实例化的对象,因此可以完成以下操作——

    ㈠直接访问成员

    ㈡作为参数,传参给其它方法

    ㈣测试的完整代码:

    1. interface Mouth {
    2. String test2 = "这是嘴类,我把它作为一个接口";
    3. void Mouth_print();
    4. }
    5. abstract class Eye {
    6. String test1 = "这是眼睛类,我把它作为一个父类";
    7. abstract void Eye_show();
    8. }
    9. public class Main {
    10. public static void main(String[] args) {
    11. test_func(
    12. new Eye() {//继承父类的匿名内部类
    13. @Override
    14. void Eye_show() {
    15. System.out.println("调用Eye父类的test成员属性:" + test1);
    16. }
    17. },//这里要注意,既然把这个匿名内部类看作一个具体对象,那么函数传多个参数的时候,显然应该用逗号隔开
    18. new Mouth() {
    19. @Override
    20. public void Mouth_print() {
    21. System.out.println("调用Mouth接口的test成员属性" + test2);
    22. }
    23. }
    24. );
    25. }
    26. static void test_func(Eye e, Mouth m) {//参数列表和传参一定要注意一一对应
    27. e.Eye_show();
    28. m.Mouth_print();
    29. }
    30. }

  • 相关阅读:
    flex布局实现左侧宽度固定,右边占满剩余宽度
    【python_学习笔记】
    Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析
    2-61 基于matlab的光学干涉仿真系统
    【FI】FB02中Coding Block字段如何设置为可修改
    4.1 数据仓库基础与Apache Hive入门
    Python的高级用法:偏函数
    第一章.线性空间和线性变换
    服务器配置openvpn,ssh连接断开
    掌动智能浅谈UI自动化测试工具的重要性
  • 原文地址:https://blog.csdn.net/liKeQing1027520/article/details/134307634