java面向对象进阶进阶篇--《成员、静态、局部、匿名内部类》

news2024/11/18 9:41:50

个人主页→VON

收录专栏→java从入门到起飞

接口和接口与抽象类综合案例

目录

 一、成员内部类

特性:

定义方式:

访问规则:

实例化:

生命周期:

静态成员:

使用场景:

示例:

Outer类 :

Text测试类:

结果展示: 

二、静态内部类

特性:

定义方式:

访问规则:

实例化:

生命周期:

静态成员:

使用场景:

示例:

Outer类:

Text测试类:

结果展示:

三、局部内部类

特性:

定义方式:

访问规则:

生命周期:

使用场景:

示例:

Outer类:

Text类:

结果展示:

四、匿名内部类(重点)

特性和使用场景:

语法:

特性:

使用场景:

 示例:

Animal类:

Swim类:

Text测试类:

Text2测试类:

结果展示:


 一、成员内部类

Java 中的成员内部类是定义在另一个类中的类。它具有与普通类相似的结构,但有一些特殊的访问规则和使用方式。

特性:

定义方式

成员内部类的定义方式如下:

public class OuterClass {
    // 外部类的成员和方法

    class InnerClass {
        // 内部类的成员和方法
    }
}

内部类 InnerClass 定义在外部类 OuterClass 的内部,可以直接访问外部类的成员变量和方法,包括私有成员。

访问规则

  • 外部类可以直接访问内部类的成员,包括私有成员。
  • 内部类可以访问外部类的所有成员,包括私有成员。
  • 内部类可以被声明为 privateprotectedpublic 或 package-private(默认),其访问权限不影响外部类对内部类的访问权限。

实例化

成员内部类需要通过外部类的实例来实例化,例如:

OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();

这里 new InnerClass() 必须依附于一个外部类的实例 outer

生命周期

成员内部类的生命周期和外部类的实例绑定,如果外部类实例被销毁,则内部类实例也无法再被访问。

静态成员

成员内部类可以包含静态成员(静态字段或静态方法),但不能有静态的顶层类(即不能声明为 static class InnerClass)。

使用场景:

  • 封装性:可以将内部类隐藏在外部类中,只有外部类才能访问,从而增强了封装性。
  • 逻辑关联:当内部类只对外部类可见并且仅用于实现外部类的一部分功能时,使用成员内部类能够更清晰地表达逻辑关联性。
  • 回调函数:内部类通常用于实现回调函数,例如事件监听器的实现方式。
  • 复杂数据结构:可以使用内部类来实现复杂的数据结构,例如迭代器等。

示例:

 
Outer类 :
package com.von.day15e;

public class Outer {
    private int a = 10;
    class Inner{
        private int a = 20;
        public void show(){
            int a = 30;
            System.out.println(Outer.this.a);//10
            System.out.println(this.a);//20
            System.out.println(a);//30
        }
    }
}
Text测试类:
package com.von.day15e;

public class Text {
    public static void main(String[] args) {
        Outer outer = new Outer();//先创建外部类的对象
        Outer.Inner inner = outer.new Inner();//再创建内部类的对象
        inner.show();
    }
}
结果展示: 

二、静态内部类

Java 中的静态内部类是定义在另一个类中且使用 static 修饰的类。静态内部类与非静态内部类(即成员内部类)有着一些重要的区别和特性。

特性:

定义方式

静态内部类的定义方式如下:

public class OuterClass {
    // 外部类的成员和方法

    static class StaticInnerClass {
        // 内部类的成员和方法
    }
}

内部类 StaticInnerClass 被声明为 static,因此它与外部类 OuterClass 的实例无关,可以直接通过 OuterClass.StaticInnerClass 的方式访问。

访问规则

  • 静态内部类可以直接访问外部类的静态成员和静态方法,包括私有的静态成员。
  • 静态内部类不能直接访问外部类的非静态成员和实例方法,因为静态内部类在没有外部类实例的情况下也可以存在。

实例化

静态内部类的实例化与普通类类似,不需要依附于外部类的实例,例如:

OuterClass.StaticInnerClass inner = new OuterClass.StaticInnerClass();

生命周期

静态内部类的生命周期与外部类的生命周期无关,它独立存在于外部类之外,直到虚拟机结束或被回收。

静态成员

静态内部类可以包含静态成员(静态字段或静态方法),但不能直接访问外部类的非静态成员。

使用场景:

  • 独立功能模块:当内部类不需要访问外部类的实例变量或方法,且希望将其组织为一个独立的类时,可以使用静态内部类。
  • 增强封装性:静态内部类可以有效地隐藏实现细节,仅暴露必要的接口给外部。
  • 工厂模式:可以将静态内部类作为工厂类,用于创建外部类的实例。
  • 辅助类:可以作为外部类的辅助类来实现一些特定的功能,例如迭代器、比较器等。

示例:

Outer类:
package com.von.day15f;

public class Outer {
    //静态内部类
    static class Inner{
        public void show1(){
            System.out.println("静态内部类非静态方法");
        }
        public static void show2(){
            System.out.println("静态内部类静态方法");
        }
    }
}
Text测试类:
package com.von.day15f;

public class Text {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();
        inner.show1();//非静态方法
        inner.show2();//静态方法
        Outer.Inner.show2();//一般用这种方法
    }
}
结果展示:

三、局部内部类

局部内部类(Local Inner Class)是定义在方法体内部的类,它与方法的局部变量具有相似的作用域。局部内部类可以访问外部类的成员变量和方法,以及方法中的 final 局部变量(Java 8 之后可以访问非 final 局部变量,但是需要保证该变量在局部内部类中不发生改变)。

特性:

定义方式

局部内部类的定义位于方法内部,形式如下:

public class OuterClass {
    // 外部类的成员和方法

    public void outerMethod() {
        class LocalInnerClass {
            // 局部内部类的成员和方法
        }

        // 在方法内部实例化局部内部类
        LocalInnerClass inner = new LocalInnerClass();
    }
}

访问规则

  • 局部内部类只在方法内部有效,出了方法就无法访问。
  • 局部内部类可以访问外部类的所有成员,包括私有成员。
  • 局部内部类可以访问方法内的局部变量,但是要求局部变量必须是 final 的或者在 Java 8 及以后版本中被隐式声明为 final。

生命周期

局部内部类的生命周期仅限于方法调用过程中,当方法返回时,局部内部类的对象也会被销毁。

使用场景

  • 当一个类仅在方法内部使用,并且对外部代码没有任何意义时,可以考虑使用局部内部类,这样能够将相关逻辑封装在一起,提高代码的局部性和封装性。
  • 在需要实现某些接口或继承某个类,并且仅在方法中使用时,局部内部类是一个比较合适的选择。

示例:

Outer类:
package com.von.day15g;

public class Outer {
    int a=10;
    public void show(){
        int b=20;
        //局部内部类
        class Inner{
            String name;
            int age;
            public void text1(){
                System.out.println("测试一");
            }
            public void text2(){
                System.out.println("测试二");
            }
        }

        Inner inner=new Inner();
        inner.text1();
        inner.text2();
        System.out.println(a);
        System.out.println(b);
    }
}
Text类:
package com.von.day15g;

public class Text {
    public static void main(String[] args)
    {
        Outer outer = new Outer();
        outer.show();
    }
}
结果展示:

四、匿名内部类(重点

 匿名内部类(Anonymous Inner Class)是一种没有显式定义类名的内部类,它允许在创建对象的同时定义类的实例。通常情况下,匿名内部类用于创建一个只需使用一次的类的实例,避免了显式定义一个新的类

特性和使用场景:

语法

匿名内部类的语法比较特殊,通常在创建对象时使用,形式如下:

interface Greeting {
    void greet();
}

public class Main {
    public static void main(String[] args) {
        Greeting greeting = new Greeting() {
            public void greet() {
                System.out.println("Hello, world!");
            }
        };

        greeting.greet(); // 输出 "Hello, world!"
    }
}

在这个例子中,Greeting 是一个接口,通过匿名内部类的方式实现了 greet() 方法。

特性

  • 匿名内部类没有类名,直接在创建对象的地方定义类的实例。
  • 匿名内部类必须继承一个类或实现一个接口,不能同时做到。
  • 匿名内部类不能定义任何静态成员、方法和初始化块。
  • 匿名内部类可以访问外部类的成员变量和方法,但是外部类的局部变量必须是 final 的或者事实上的 final(Java 8+)。

使用场景

  • 事件监听器:在GUI编程中,常常使用匿名内部类作为事件监听器的实现。
  • 线程类:在启动线程时,可以通过匿名内部类直接定义线程类的实例。
  • 集合类的参数:在某些集合类的方法参数中,需要传递接口实例,可以使用匿名内部类快速实现接口方法。

 示例:

Animal类:
package com.von.day15g;

public class Animal {
    public void eat() {
        System.out.println("吃东西");
    }
}
Swim类:
package com.von.day15g;

public interface Swim {
    abstract void swim();
}
Text测试类:
package com.von.day15g;

public class Text {
    public static void main(String[] args){
        new Swim(){
            @Override
            public void swim() {
                System.out.println("匿名内部类实现接口");
            }
        }.swim();
        new Animal(){
            @Override
            public void eat() {
                System.out.println("匿名内部类实现抽象类");
            }
        }.eat();
        methon(
            new Animal(){
                @Override
                public void eat() {
                    System.out.println("狗吃骨头");
                }
            });
    }
    public static void methon(Animal a){
        a.eat();
    }
}
package com.von.day15g;

public class Text {
    public static void main(String[] args){
        new Swim(){
            @Override
            public void swim() {
                System.out.println("匿名内部类实现接口");
            }
        }.swim();
        new Animal(){
            @Override
            public void eat() {
                System.out.println("匿名内部类实现抽象类");
            }
        }.eat();
        methon(
            new Animal(){
                @Override
                public void eat() {
                    System.out.println("狗吃骨头");
                }
            });
    }
    public static void methon(Animal a){
        a.eat();
    }
}
Text2测试类:
package com.von.day15g;

public class Text2 {
    public static void main(String[] args) {
        Swim s =  new Swim(){

            @Override
            public void swim() {
                System.out.println("游泳");
            }
        };
        s.swim();

        new Swim(){
            @Override
            public void swim() {
                System.out.println("游泳");
            }
        }.swim();
    }
}
结果展示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1949205.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

快速入门了解Ajax

博客主页:音符犹如代码系列专栏:JavaWeb关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ Ajax的初识 意义:AJAX(Asynchronous JavaScript and…

C语言 | Leetcode C语言题解之第287题寻找重复数

题目&#xff1a; 题解&#xff1a; int findDuplicate(int* nums, int numsSize){int *b(int*)calloc(100001,sizeof(int));for(int i0;i<numsSize;i){ b[nums[i]];if(b[nums[i]]2) return nums[i];}return 0;}

【C语言】 二叉树创建(结构体,先序遍历,中序遍历,后续遍历)

二叉树的创建&#xff1a;首先先定义一个结构体&#xff0c;里面包含数据&#xff08;data&#xff09;&#xff0c;指向左子树的指针&#xff08;L&#xff09;&#xff0c;指向右子树的指针&#xff08;R&#xff09;三个部分 在创建树的函数中&#xff0c;首先先输入…

内网对抗-隧道技术篇防火墙组策略HTTP反向SSH转发出网穿透CrossC2解决方案

知识点&#xff1a; 1、C2/C2上线-CrossC2插件-多系统平台支持 2、隧道技术篇-应用层-SSH协议-判断&封装&建立&穿透 3、隧道技术篇-应用层-HTTP协议-判断&封装&建立&穿透隧道技术主要解决网络通讯问题&#xff1a;遇到防火墙就用隧道技术&#xff0c;…

Mysql第五次作业 触发器和存储过程

1、建库建表 建立触发器&#xff0c;订单表中增加订单数量后&#xff0c;商品表商品数量同步减少对应的商品订单出数量,并测试 建立触发器&#xff0c;实现功能:客户取消订单&#xff0c;恢复商品表对应商品的数量 建立触发器&#xff0c;实现功能:客户修改订单&#xff0c;商品…

Golang | Leetcode Golang题解之第284题窥视迭代器

题目&#xff1a; 题解&#xff1a; type PeekingIterator struct {iter *Iterator_hasNext bool_next int }func Constructor(iter *Iterator) *PeekingIterator {return &PeekingIterator{iter, iter.hasNext(), iter.next()} }func (it *PeekingIterator) hasNe…

鸿蒙应用框架开发【多HAP】程序框架

多HAP 介绍 本示例展示多HAP开发&#xff0c;简单介绍了多HAP的使用场景&#xff0c;应用包含了一个entry HAP和两个feature HAP&#xff0c;两个feature HAP分别提供了音频和视频播放组件&#xff0c;entry中使用了音频和视频播放组件。 三个模块需要安装三个hap包&#xff…

Milvus 向量数据库进阶系列丨部署形态选型

本系列文章介绍 在和社区小伙伴们交流的过程中&#xff0c;我们发现大家最关心的问题从来不是某个具体的功能如何使用&#xff0c;而是面对一个具体的实战场景时&#xff0c;如何选择合适的向量数据库解决方案或最优的功能组合。在 “Milvus 向量数据库进阶” 这个系列文章中&…

提交高通量测序处理数据到 GEO --- 操作流程

❝ 写在前面 由于最近在提交课题数据到 NCBI 数据库&#xff0c;整理了相关笔记。本着自己学习、分享他人的态度&#xff0c;分享学习笔记&#xff0c;希望能对大家有所帮助。推荐先按顺序阅读往期内容&#xff1a; 1. 提交高通量测序数据到 GEO --- 说明书 2. 提交高通量测序原…

Hello SLAM(在Linux中实现第一个C++程序)

首先需要安装vim编辑器&#xff0c;输入命令 sudo apt install vim 在Ubuntu上安装好vim编辑器后&#xff0c;创建路径&#xff08;/home/slambook/ch2&#xff09;&#xff0c;在该路径下创建一个cpp文档&#xff08;touch hello.c&#xff09;&#xff0c;通过vim编辑器进行…

Docker安装kkFileView实现在线文件预览

kkFileView为文件文档在线预览解决方案,该项目使用流行的spring boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等 官方文档地址:https://kkview.cn/zh-cn/docs/production.html 一、拉取镜像 do…

MYSQL 第四次作业

任务要求&#xff1a; 具体操作&#xff1a; 新建数据库&#xff1a; mysql> CREATE DATABASE mydb15_indexstu; Query OK, 1 row affected (0.01 sec) mysql> USE mydb15_indexstu; Database changed 新建表&#xff1a; mysql> CREATE TABLE student( ->…

【人工智能】AI绘画:科技与艺术交汇的新时代

文章目录 &#x1f34a;AI绘画:开启艺术创作新纪元AI绘画技术发展&#xff1a;算法与艺术的完美交融AI绘画的工作原理与创意生成AI绘画的应用 AI绘画工具介绍 &#x1f34a;AI绘画:开启艺术创作新纪元 人工智能正以前所未有的力量重塑我们的世界&#xff0c;而AI绘画作为这股科…

Unity UGUI 之 事件接口

本文仅作学习笔记与交流&#xff0c;不作任何商业用途 本文包括但不限于unity官方手册&#xff0c;唐老狮&#xff0c;麦扣教程知识&#xff0c;引用会标记&#xff0c;如有不足还请斧正 本文在发布时间选用unity 2022.3.8稳定版本&#xff0c;请注意分别 1.什么是事件接口&…

Docker(十)-Docker运行elasticsearch7.4.2容器实例

1.下载镜像 1.1存储和检索数据 docker pull elasticsearch:7.4.2 1.2可视化检索数据 docker pull kibana:7.4.22.创建elasticsearch实例 创建本地挂载数据卷配置目录 mkdir -p /software/elasticsearch/config 创建本地挂载数据卷数据目录 mkdir -p /software/elasticse…

单元测试--Junit

Junit是Java的单元测试框架提供了一些注解方便我们进行单元测试 1. 常用注解 常用注解&#xff1a; TestBeforeAll&#xff0c;AfterAllBeforeEach&#xff0c;AfterEach 使用这些注解需要先引入依赖&#xff1a; <dependency><groupId>org.junit.jupiter<…

【第二天】计算机网络 HTTP请求报文和响应报文是什么样的 HTTP请求方式有哪些 GET请求和POST请求的区别

HTTP请求报文和响应报文是什么样的&#xff1f; 我去&#xff0c;以前都没怎么研究过这个。 客户端发送一个请求给服务器&#xff0c;服务器根据请求报文中的信息进行处理&#xff0c;并将处理结果放到响应报文中返回给客户端。 URL HTTP使用URL (Uniform Resource Locator&…

leetcode-148. 排序链表

题目描述 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [4,2,1,3] 输出&#xff1a;[1,2,3,4]示例 2&#xff1a; 输入&#xff1a;head [-1,5,3,4,0] 输出&#xff1a;[-1,0,3,4,5]示例 3&#x…

【Docker】Windows11环境下的安装

前置依赖环境配置 确保虚拟化开启 搜索栏直接搜索如下功能 勾选下面两个选项&#xff0c;确定 重启电脑&#xff0c;以管理员身份打开PowerShell wsl --status wsl --update打开微软应用商店选择一个Ubuntu版本下载并打开 输入一个用户名和密码 然后就可以在Windows下使…

Hyperledger Fabric 网络体验 - 网络启动过程概览

进入fabric-samples/test-network目录&#xff0c;执行指令&#xff1a; ./network.sh up -i 2.5执行完指令能看到fabric已经启动。 作为第一次Fabric网络体验&#xff0c;网络启动主要包含三个操作&#xff0c;分别是生成配置文件、启动网络和操作网络。 配置文件 使用cr…