Java基础_内部类

news/2024/7/24 12:52:47 标签: java, 开发语言

文章目录

    • 1.基本介绍
        • 1.定义:
        • 2.基本语法:
        • 3.内部类的分类
    • 2.局部内部类
        • 1.快速入门
        • 2.局部内部类的使用
    • 3.匿名内部类
        • 1.匿名内部类实现接口
        • 2.匿名内部类继承抽象类
        • 3.匿名内部类细节
        • 4.匿名内部类最佳实践
          • 1.匿名内部类作为实参传入函数
          • 2.匿名内部类课堂练习
    • 4.成员内部类
        • 成员内部类的使用
    • 5.静态内部类
        • 静态内部类的使用

1.基本介绍

1.定义:

一个类的内部又完整的嵌套了另一个类结构,被嵌套的类称为内部类,嵌套其他类的类被称为外部类。

2.基本语法:

image-20231211202901842

3.内部类的分类
  1. 定义在外部局部位置上(比如方法内):
    1. 局部内部类(有类名)
    2. 匿名内部类(没有类名)
  2. 定义在外部类的成员位置上
    1. 成员内部类(没用static修饰)
    2. 静态内部类(使用static修饰)

2.局部内部类

1.快速入门
java">package innerclass;

public class LocalInnerClass {
    public static void main(String[] args) {
        new Outer02().m1();
    }
}

class Outer02 { //外部类
    private int n1 = 100;

    private void m2() { //私有方法
        System.out.println("这是外部类的私有方法");
    }

    public void m1() {
        class Inner02 { //局部内部类,是放在代码块或者方法中(本质仍然是一个类)
            public void f1() {
                System.out.println("外部类的私有属性:" + n1); //局部内部类可以直接访问外部类的所有私有成员

            }
        }
        class Inner03 extends Inner02 { //局部内部类可以被继承
            public void f2() {
                super.f1(); //可以访问父类的方法
                m2();//还可以访问外部类的私有方法
            }
        }
        new Inner03().f2(); //在方法中创建局部内部类的对象然后调用方法
    }

}

2.局部内部类的使用
  1. 局部内部类既是一个局部变量又是一个类

  2. 局部内部类可以访问外部类的所有成员,包括私有的

  3. 不能添加访问修饰符,因为他的地位是一个局部变量,但是可以使用final修饰

  4. 作用域:仅仅在定义他的方法或者代码块中

  5. 外部类访问局部内部类的方式,在方法或者代码块中声明局部内部类的对象然后调用

  6. 外部其他类不能访问局部内部类,因为局部内部类地位是一个局部变量

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

    java">外部类名.this.成员
    

    外部类名.this的意思是外部类的一个对象,就相当于普通类中的this,谁调用的这个方法,则这个对象就是谁

  8. 代码实例

    java">package innerclass;
    
    public class LocalInnerClass {
        public static void main(String[] args) {
            new Outer02().m1();
        }
    }
    
    class Outer02 { //外部类
        private int n1 = 100;
    
        public void m1() {
            class Inner02 { //局部内部类,是放在代码块或者方法中(本质仍然是一个类)
                int n1 = 200; //与外部类中的属性重名,默认遵循就近原则
                public void f1() {
                    System.out.println("局部内部类中的n1 = " + n1); //根据就近原则,访问了局部内部类中的n1
                    System.out.println("外部类中的n1 = " + Outer02.this.n1);
                }
            }
            new Inner02().f1();
        }
    }
    

3.匿名内部类

1.匿名内部类实现接口
  1. 需求:想使用一个接口,并创建对象,但是只使用一次

  2. 传统方式:写一个类,实现接口,并创建对象

  3. 可以使用匿名内部类来简化开发

  4. jdk底层:创建了一个匿名内部类,实现了接口,然后返回一个这个匿名内部类的对象

  5. 代码实例

    java">package innerclass;
    
    public class AnonymousInnerClass {
        public static void main(String[] args) {
            new Out().method();
        }
    }
    interface IA {
        void cry();
    }
    class Out { //外部类
        public void method() {
            IA tiger = new IA() { //编译类型是IA , 运行类型是匿名内部类Out$1
                @Override
                public void cry() {
                    System.out.println("老虎在哭");
                }
            }; //匿名内部类,底层进行了,写一个匿名内部类,实现了接口IA,然后返回了一个对象
            tiger.cry();
            System.out.println("匿名内部类的名字:" + tiger.getClass());
        }
    }
    

    image-20231211215756320

2.匿名内部类继承抽象类
  1. 匿名内部类可以继承普通类或者抽象类

  2. jdk底层:创建一个匿名内部类,继承了抽象类,重写抽象类的抽象方法,返回一个匿名内部类的对象,如果有构造器相当于调用了父类的构造器

  3. 代码实例

    java">package innerclass;
    
    public class AnonymousInnerClass {
        public static void main(String[] args) {
            new Out().method();
        }
    }
    abstract class Father1 {
        public Father1(String name) {
    
        }
        public abstract void cry(); //抽象方法
    }
    class Out { //外部类
        public void method() {
            Father1 father = new Father1("父亲") { //匿名内部类整个过程相当于,1.创建一个匿名内部类 2.继承了Father类 3.返回一个匿名内部类的对象
                //这个匿名内部类继承了抽象类则需要重写抽象方法
                @Override
                public void cry() {
                    System.out.println("匿名内部类重写了父类的抽象方法");
                }
            };
            father.cry();
        }
    }
    

image-20231212195939957

3.匿名内部类细节
  1. 匿名内部类是以一个类似于类的形式展示,但是其实他是这个类返回的一个对象,所以可以直接使用这个匿名内部类对象来访问里面的成员image-20231212203652491

  2. 匿名内部类可以直接访问外部类的所有成员,包括私有的

  3. 不能给匿名内部类直接添加访问修饰符,因为匿名内部类本身也是一个局部变量

  4. 匿名内部类的作用域:仅仅在定义它的方法或代码块中

  5. 匿名内部类访问外部类的成员的方式是直接访问

  6. 如果内部类的属性跟外部类的属性冲突,则可以使用类名.this.属性名的方式访问外部类的属性

  7. 其他外部类不能访问匿名内部类,因为匿名内部类只是一个局部变量

  8. 代码实例

    java">package innerclass;
    
    public class AnonymousInnerClassDetail {
        public static void main(String[] args) {
            new Outer05().f1();
        }
    }
    class Person {
        public void hi(String name) {
            System.out.println("你好:" + name);
        }
    }
    class Outer05 {
        private int n1 = 99;
        public void f1() {
            new Person() { //匿名内部类继承了Person类
                @Override
                public void hi(String name) { //重写了hi方法
                    super.hi(name);
                }
            }.hi("小明");//这相当于匿名内部类的一个对象可以直接调用方法
    
            new Person() {
                int n1 = 100; //这里的属性跟外部类的属性重名了
                public void printn1() {
                    System.out.println("外部类的n1:" + Outer05.this.n1); //使用外部类名.this.属性名来访问与内部类重名的外部属性
                    System.out.println("内部类的n1:" + n1);
                }
            }.printn1();
    
        }
    }
    
    

    image-20231212205039151

4.匿名内部类最佳实践
1.匿名内部类作为实参传入函数
java">package innerclass;

public class InnerclassExercise01 {
    public static void main(String[] args) {
        f1(new IL() {
            @Override
            public void show() {
                System.out.println("我实现了接口的IL方法");
            }
        }); //使用匿名内部类直接作为实参传入函数
    }
    public static void f1(IL li) {
        li.show();
    }
}
interface IL {
    void show();
}
2.匿名内部类课堂练习

image-20231212212321281

  1. 代码

    java">package innerclass;
    
    public class InnerclassExercise02 {
        public static void main(String[] args) {
            new CellPhone().alarmclock(new Bell() {
                @Override
                public void ring() {
                    System.out.println("懒猪起床了");
                }
            });
            new CellPhone().alarmclock(new Bell() {
                @Override
                public void ring() {
                    System.out.println("小伙伴上课了");
                }
            });
        }
    }
    interface Bell {
        void ring();
    }
    class CellPhone {
        public void alarmclock(Bell bell) {
            bell.ring();
        }
    }
    
  2. 结果image-20231212212603366

4.成员内部类

成员内部类的使用
  1. 说明:成员内部类是定义在外部类的成员位置,并且没有static修饰

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

  3. 可以添加任何访问修饰符,因为他的定位就是一个成员

  4. 作用域:和外部类的其他成员一样

  5. 成员内部类访问外部类的成员可以直接访问,当成员内部类的成员跟外部类的成员重名的时候,使用外部类名.this.成员名来访问

  6. 外部类访问成员内部类,创建对象访问

  7. 代码实例

    java">package innerclass;
    
    public class MemberInnerClass01 {
        public static void main(String[] args) {
            new Outer01().f1();
            Outer01 outer01 = new Outer01();
        }
    }
    class Outer01 { //外部类
        private int n1 = 10;
        public String name = "张三";
        public class Innter01 { //成员内部类
            public String name = "李四"; //成员内部类的属性跟外部类重名
            public void say() {
                System.out.println("Outer01的n1:" + n1 + " Outer01的name:" + Outer01.this.name); //成员内部类可以访问外部类的所有成员,当重名的时候需要使用外部类名.this.属性名来访问
            }
        }
        public void f1() {
            //使用成员内部类
            Innter01 innter01 = new Innter01(); //外部类访问成员内部类,创建对象访问
            innter01.say();
        }
    }
    
    

    image-20231213194515782

  8. 外部其他类访问成员内部类有两种方式

    1. 通过外部类的实例来访问并创建一个成员内部类的实例
    2. 在外部类中暴露一个方法返回成员内部类的实例
    java">package innerclass;
    
    public class MemberInnerClass02 {
        public static void main(String[] args) {
            //外部其他类访问成员内部类的第一种方式,使用外部类的实例来访问内部类并创建对象
            Outer06.Innter innter = new Outer06().new Innter();
            innter.method();
            //第二种方式,在外部类中写一个方法直接返回成员内部类的对象
            Outer06.Innter innter1 = new Outer06().getInnter();
            innter1.method();
    
        }
    }
    class Outer06 { //外部类
        public class Innter { //成员内部类
            public void method() {
                System.out.println("我是成员内部类");
            }
        }
        public Innter getInnter() { //向外暴露一个方法来获得成员内部类的对象
            return new Innter();
        }
    }
    
    

5.静态内部类

静态内部类的使用
  1. 说明:静态内部类是有static的在成员位置的内部类

  2. 可以直接访问外部类的所有静态成员,包括私有的,但是不能直接访问非静态成员

  3. 可以添加任何访问修饰符,因为他的地位是一个成员

  4. 作用域:同其他的成员

  5. 静态内部类访问外部类的静态成员可以直接访问,如果重名,则使用外部类名.成员名来访问(不加this的原因静态内部类只能访问静态成员,所以就没有加this的必要)

  6. 外部类访问静态内部类 创建对象再访问

  7. 外部其他类访问静态内部类有三种方式

    java">package innerclass;
    
    public class StaticInnerClass01 {
        public static void main(String[] args) {
            //外部其他类访问静态内部类的第一种方式,创建对象访问
            Outer07.Inner02 inner02 = new Outer07.Inner02(); //因为他是静态的所以是是属于类的可以直接用类名访问
            inner02.say();
            //外部其他类访问静态内部类的第二种方式,在外部类中暴露一个普通方法返回静态内部类的实例
            Outer07.Inner02 inner021 = new Outer07().getInner02();
            inner021.say();
            //外部其他类访问静态内部类的第三种方式,在外部类中暴露一个静态方法返回静态内部类的实例
            Outer07.Inner02 inner022 = Outer07.getInner02_();
            inner022.say();
        }
    }
    class Outer07 { //外部类
        public static class Inner02 {
            public void say() {
                System.out.println("我是静态内部类");
            }
        }
        public Inner02 getInner02() { //普通方法返回静态内部类实例
            return new Inner02();
        }
        public static Inner02 getInner02_() { //静态方法返回静态内部类实例
            return new Inner02();
        }
    }
    
    
  8. 练习image-20231213205751598image-20231213205815184


http://www.niftyadmin.cn/n/5427433.html

相关文章

IDEA如何切换git账户

一、首先设置idea的密码不保存 二、找到你的windos的凭据管理器,直接在电脑里面搜索就行。 把已经有的git的凭据删掉,然后重启IDEA,拉取代码,就会弹框来让你输入账号。 注意:将系统弹出的账号密码框关掉,…

LeetCode[题解] 2864. 最大二进制奇数

题目 给你一个 二进制 字符串 s ,其中至少包含一个 ‘1’ 。 你必须按某种方式 重新排列 字符串中的位,使得到的二进制数字是可以由该组合生成的 最大二进制奇数 。 以字符串形式,表示并返回可以由给定组合生成的最大二进制奇数。 注意 返回…

Docker启动安装nacos(踩过坑版)

1、Docker 拉取镜像 docker pull nacos/nacos-server:v2.1.0 2、创建宿主机挂载目录 mkdir -p /mydata/nacos/logs/ mkdir -p /mydata/nacos/conf/ 3、启动nacos并复制文件到宿主机,关闭容器 启动容器 docker run -p 8848:8848 --name nacos -d nacos/nacos-se…

bootstrap精选模板tabler下载

官网演示: https://mb.bootcss.com/themes/tabler/index.html 在线预览: https://tabler.io/preview Github 开源地址: https://github.com/tabler/tabler Tabler 项目特点: 现代化设计: Tabler 采用现代化的设计…

(差分)胡桃爱原石

琴团长带领着一群胡桃准备出征,进攻丘丘人,出征前,琴团长根据不同胡桃的战力,发放原石作为军饷,琴团长分批次发放,每批次会给连续的几个胡桃发放相同的原石,琴团长最后想知道给每个胡桃发放了多…

ChatGPT浪潮来袭!谁先掌握,谁将领先!

任正非在接受采访时说 今后职场上只有两种人, 一种是熟练使用AI的人, 另一种是创造AI工具的人。 虽然这个现实听起来有些夸张的残酷, 但这就是我们必须面对的事实 📆 对于我们普通人来说,我们需要努力成为能够掌握…

web学习笔记(二十八)

目录 1.JSON 1.1JSON简介 1.2JSON的语法 1.3JSON字符串分类 1.4JSON方法 2.数据存储 2.1会话存储 2.1.1会话存储的特点 2.1.2会话存储的常用方法 2.2本地存储 2.2.1本地存储的特点 2.2.2本地存储的常用方法 2.3两者的共同点 1.JSON 1.1JSON简介 JSON&#x…

为什么使用RedisDesktopManager可以连上redis,微服务似乎无法访问redis

通过测试并观察,RedisDesktopManager虽然可以连上redis,但偶尔会很慢很慢(20秒左右)才能连上,那会不会是微服务的超时时间太短导致连不上呢? 改了服务的配置,没有任何效果。 spring:main: allo…