Java特别篇--匿名对象与匿名内部类

文章目录

  • 一、匿名对象
  • 二、匿名内部类

很多小伙伴对匿名对象和匿名内部类的写法有点陌生,这里专门写一篇来帮助大家认识一下他们的写法。

一、匿名对象

比如现在有一个Student类,里面啥也没有写:

/**
 * ClassName: Student
 * Package: PACKAGE_NAME
 * Description:
 *
 * @Author 雨翼轻尘
 * @Create 2024/1/31 0031 11:39
 */
public class Student {

}

然后还有一个测试类Test

/**
 * ClassName: Test
 * Package: PACKAGE_NAME
 * Description:
 *
 * @Author 雨翼轻尘
 * @Create 2024/1/31 0031 11:39
 */
public class Test {
    public static void main(String[] args) {
        //类->对象  格式:类名Student 对象名stu = new 类名Student();
        Student stu=new Student();
    }
}

🗳️类->对象

格式:类名Student 对象名stu = new 类名Student();

如下:

public class Test {
    public static void main(String[] args) {
        //类->对象  格式:类名Student 对象名stu = new 类名Student();
        Student stu=new Student();
    }
}

现在打印出来就是地址值

image.png

如果这样,也是地址值

image.png

new一次,就会创建一个对象,相当于在堆中开辟了一块空间,所以地址值都不一样,如下:

public class Test {
    public static void main(String[] args) {
        //类->对象  格式:类名Student 对象名stu = new 类名Student();
        Student stu=new Student();
        System.out.println(stu);    //test.Student@4eec7777
        System.out.println(new Student());  //test.Student@3b07d329
        System.out.println(new Student());  //test.Student@41629346
    }
}

上面的stu是有名字的对象,而现在的new Student()没有对象名,叫做匿名对象

有了new关键字,就表示在堆里面创建了一个新的空间。


现在在Student类里面加上属性,比如:

public class Student {
    String name;    //姓名
}

正常情况下,name可以赋值:

public class Test {
    public static void main(String[] args) {
        //类->对象  格式:类名Student 对象名stu = new 类名Student();
        Student stu=new Student();
        System.out.println(stu);    //test.Student@4eec7777
        stu.name="张三";
        System.out.println(stu.name);   //张三

    }
}

打印出来就是“张三”:

image.png

🎲那么new Student()可以给name赋值吗?

是可以的。

它是一个匿名对象,虽然没有名字,但是它可以给属性赋值的。如下:

public class Test {
    public static void main(String[] args) {
        System.out.println(new Student().name="李四");  //test.Student@3b07d329
        System.out.println(new Student());  //test.Student@41629346
    }
}

输出:

image.png


匿名对象”只不过是一个没有名字的对象而已,依然是一个对象。

若是方法依然可以调用的,比如现在写一个方法eat,如下:

public class Student {
    String name;    //姓名

    public void eat(){
        System.out.println("使劲吃...");
    }
}

测试类里面:

public class Test {
    public static void main(String[] args) {
        //类->对象  格式:类名Student 对象名stu = new 类名Student();
        Student stu=new Student();
        System.out.println(stu);    //test.Student@4eec7777
        stu.name="张三";
        System.out.println(stu.name);   //张三
        stu.eat();

        System.out.println(new Student().name="李四");  //test.Student@3b07d329
        System.out.println(new Student());  //test.Student@41629346
        new Student().eat();
    }
}

输出结果:

image.png

像这样直接new了一个类名,但是没有给对象名的,叫做“匿名对象”。

区别就是,有名的对象它可以多次使用,而匿名对象却只能使用一次。

二、匿名内部类

提供一个接口IA,里面写一个抽象方法play,如下:

package test;

/**
 * ClassName: IA
 * Package: test
 * Description:
 *
 * @Author 雨翼轻尘
 * @Create 2024/1/31 0031 12:08
 */
public interface IA {
    //抽象方法
    void play();
}

抽象方法省略了public abstract

抽象方法要想重写,需要有子类去实现这个接口

接下来写一个实现类IAImpl,将接口里面的抽象方法重写一下,如下:

package test;

/**
 * ClassName: IAImpl
 * Package: test
 * Description:
 *
 * @Author 雨翼轻尘
 * @Create 2024/1/31 0031 12:12
 */
public class IAImpl implements IA{
    @Override
    public void play() {
        System.out.println("打游戏...");
    }
}

然后再来一个测试类IATest,以多态的方式创建接口:

package test;

/**
 * ClassName: IATest
 * Package: test
 * Description:
 *
 * @Author 雨翼轻尘
 * @Create 2024/1/31 0031 12:14
 */
public class IATest {
    public static void main(String[] args) {
        IA ia=new IAImpl(); //多态
    }
}

IA ia=new IAImpl(); ,接口不能传对象,口诀:多态–“父父new子”。

实现类可以看成继承关系。

现在来使用ia调用play方法:

public class IATest {
    public static void main(String[] args) {
        IA ia=new IAImpl(); //多态
        ia.play();	//编译看左,运行看右
    }
}

输出:

image.png

ia.play();编译看左,运行看右”,接口IA里面有play方法,它被实现类IAImpl重写了,所以执行的时候是看实现类里面的。


现在我们来看一下这个蓝色部分,这个括号里面只有一个方法的重写:

image.png

之前说接口不能new,我们来看一下这样:

image.png

🎲看一下刚才的两个蓝色部分,有什么区别?

image.png

没有区别!只不过右边多了一个最后的分号。

既然花括号里面的内容和实现类的一模一样,那我们可以使用i调用里面的方法play,如下:

public class IATest {
    public static void main(String[] args) {
        IA ia=new IAImpl(); //多态
        ia.play();  //编译看左,运行看右

        System.out.println("------------------");

        IA i=new IA() {
            @Override
            public void play() {
                System.out.println("打游戏哈哈哈...");
            }
        };

        i.play();
    }
}

打印输出:

image.png

可以看到,调用的是花括号里面重写IA接口的方法。

我们new了一个接口之后,后面的大括号里面可以看作一个类的结构。如下:

image.png

在花括号里面是对方法的重写,重写的是IA接口的抽象方法


现在写一个IB接口

public interface IB {
    //抽象方法
    void sleep();
}

再写一个测试类IBTest

public class IBTest {
    public static void main(String[] args) {

    }
}

目前IB接口没有实现类,还可以创建对象吗?

可以的,如下:

public class IBTest {
    public static void main(String[] args) {
        IB ib=new IB() {
            @Override
            public void sleep() {

            }
        };
    }
}

这个结构和它的实现类结构是一样的(蓝色部分):

image.png

现在就不需要接口的实现类了,上面蓝色部分就是它的匿名实现类

通过ib.sleep()来调用重写的抽象方法:

public class IBTest {
    public static void main(String[] args) {
        IB ib=new IB() {
            @Override
            public void sleep() {
                System.out.println("睡觉...");
            }
        };

        ib.sleep();
    }
}

输出:

image.png

这就是匿名内部类,new的接口,相当于是把实现类的结构拿了过来,重写了一下。


🍰还有一种写法。

刚才说了匿名对象,可以直接拿匿名对象去调用方法。

同样,我们还可以使用匿名内部类直接调用方法

这个叫做创建“匿名实现类的有名对象”,如下结构:

IB ib = new IB(){
    //sleep()方法的重写
};
ib.sleep();	//用ib调用方法sleep()

现在我们直接new一个接口IB

new IB(){
    //sleep()方法的重写
}

然后直接用它调用sleep()方法,如下:

new IB(){
    //sleep()方法的重写
}.sleep();

🌱代码

public class IBTest {
    public static void main(String[] args) {
        IB ib=new IB() {
            @Override
            public void sleep() {
                System.out.println("睡觉...");
            }
        };

        ib.sleep();

        System.out.println("-------");

        new IB(){
            @Override
            public void sleep() {
                System.out.println("晚安喽");
            }
        }.sleep();
    }
}

🍺输出

image.png

这里的ib就表示:

image.png

那就可以直接拿它调用sleep()方法:

image.png


🚗看一下正常的一般写法:

image.png

再看一下这两种方式:

image.png

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

kettle通过severice_name连接oracle数据源踩坑

最近在研究kettle做数据抽取核对,按照官网安装kettle后无法连接oracle 坑1:kettle 连接oracle的数据库名指的是sidname 而非severicename,前期一直使用severicename 如下始终报错 注意区分下: SID:一个数据库可以有多个实例&…

食品信息管理系统java项目ssm项目springboot项目

食品信息管理系统java项目ssm项目springboot项目,增删改查均已实现,有批量删除 前端技术: JavaScript,Layui,Html5 后端技术: Java,MySql,Spring,Spring Mvc,SpringBoot&#xff0…

AI算力专题:AI时代领先者,大装置+大模型推动AGI落地

今天分享的是AI算力系列深度研究报告:《AI算力专题:AI时代领先者,大装置大模型推动AGI落地》。 (报告出品方:中银证券) 报告共计:28页 四核驱动引领智慧科技新潮流 商汤是一家行业领先的人工…

幻兽帕鲁服务器多少钱——幻兽帕鲁服务器价格介绍

2024年幻兽帕鲁服务器价格表更新,阿里云、腾讯云和华为云Palworld服务器报价大全,4核16G幻兽帕鲁专用服务器阿里云26元、腾讯云32元、华为云26元,阿腾云atengyun.com分享幻兽帕鲁服务器优惠价格表,多配置报价: 幻兽帕鲁…

2023年09月CCF-GESP编程能力等级认证Python编程二级真题解析

一、单选题(共15题,共30分) 第1题 我国第一台大型通用电子计算机使用的逻辑部件是 ( )。 A:集成电路 B:大规模集成电路 C:晶体管 D:电子管 答案:D 第2题 下列流程图的输出结果是( )? A:5 12 B:12 5 C:5 5 D:12 12 答案:B 第3题 如果要找出整数 a …

【经典项目】Java小游戏 —— 弹力球

一、功能需求 设计一个Java弹球小游戏的思路如下: 创建游戏窗口:使用Java图形库(如Swing或JavaFX)创建一个窗口,作为游戏的可视化界面。 绘制游戏界面:在游戏窗口中绘制游戏所需的各个元素,包括…

在Mixamo网站上,下载的动画导入unity给自己的模型添加后出错怎么解决

在Mixamo网站上,下载的动画导入unity给自己的模型添加后出错 一、在Mixamo下载的模型可以正常使用二、在自己的模型和unity自带模型上就出错1.解决方法2.解决成功 注意 一、在Mixamo下载的模型可以正常使用 二、在自己的模型和unity自带模型上就出错 1.解决方法 选…

Python XPath解析html出现⋆解决方法 html出现#123;解决方法

前言 爬网页又遇到一个坑,老是出现乱码,查看html出现的是&#数字;这样的。 网上相关的“Python字符中出现&#的解决办法”又没有很好的解决,自己继续冲浪,费了一番功夫解决了。 这算是又加深了一下我对这些iso、Unicode编…

Log4j2-11-log4j2 Layout 布局入门介绍

Layout 布局 Appender使用Layout将LogEvent格式化为一种表单,以满足将要消费日志事件的任何需求。 在Log4j中。x和Logback布局被期望将事件转换为字符串。 在Log4j 2布局返回一个字节数组。这使得Layout的结果可以在更多类型的appender中使用。然而,这…

1.30号c++

浅拷贝和深拷贝(重点) 1> 每个类中系统都会提供一个默认的拷贝构造函数,如果程序员显性定义出拷贝构造函数,则系统取消默认提供。 2> 系统提供的拷贝构造函数,是将一个类对象的所有数据成员给另一个对象的所有…

###C语言程序设计-----C语言学习(8)## 斐波那契数列问题,素数问题,人数分配问题。

前言:感谢您的关注哦,我会持续更新编程相关知识,愿您在这里有所收获。如果有任何问题,欢迎沟通交流!期待与您在学习编程的道路上共同进步。 今天,我们主要分享三个问题如何用C语言去求解,1.斐波…

图片怎么裁剪成想要的尺寸?教你快速图片裁剪的方法

图片怎么裁剪成想要的尺寸?图片裁剪属于我们日常生活中比较常见的图片处理方式了,不管是改变图片打下,还是需要将图片中一些不需要的部分裁减掉,都需要用到这个功能,除了使用软件之外,我们还可以通过在线裁…

【Django自学】Django入门:如何使用django开发一个web项目(非常详细)

测试机器:windows11 x64 python版本:3.11 一、安装Django 安装步骤非常简单,使用pip安装就行 pip install django安装完成之后,python的 Scripts 文件夹下,会多一个 django-admin.exe (管理创建django项目的工具)。…

超声波风速风向传感器的优势及应用

TH-WQX2随着科技的不断发展,传感器技术日益成为众多领域中不可或缺的一部分。其中,超声波风速风向传感器凭借其独特的优势,在气象、能源、环保等领域中发挥着越来越重要的作用。 首先,超声波风速风向传感器无需机械转动部件&#…

【Vue】2-10、Vue 组件

一、组件化开发 组件化开发指的是根据封装的思想,把页面上可重用的 UI 结构封装为组件,从而方便项目的开发和维护。 二、Vue 组件的组成 template:组件的模板结构script:组件的 JavaScript 行为style:组件的样式 &…

Vim实战:使用 Vim实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整策略设置混合精度,DP多卡,EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试完整的代码 在上…

C++提取ICO图标(PE文件资源提取)

最近需要写一个提取EXE或者DLL图标资源的功能, 网上找了很久, 要么功能不好用, 最后结果如下: 1.很多是加载为HICON句柄后转换为图片保存, 全损画质..., 2.后来找了个还能用的, 详见 https://github.com/TortoiseGit/TortoiseGit/blob/master/src/Utils/IconExtractor.cpp …

git远程仓库基本操作

目录 gitremote (查看远程仓库) git remote add [仓库名] [url] git clone [url](克隆远程仓库到本地) git push [名][分支名](提交到远程仓库)​编辑 git pull [名][分支名]从远程仓库拉取​编辑 注意操作…

opencv学习 特征提取

内容来源于《opencv4应用开发入门、进阶与工程化实践》 图像金字塔 略 拉普拉斯金字塔 对输入图像进行reduce操作会生成不同分辨率的图像,对这些图像进行expand操作,然后使用reduce减去expand之后的结果,就会得到拉普拉斯金字塔图像。 …

Java 代理详解

Java 代理详解 文章目录 Java 代理详解1. 代理模式2. 静态代理3. 动态代理3.1. JDK 动态代理机制3.1.1. 介绍3.1.2. JDK 动态代理类使用步骤3.1.3. 代码示例 3.2. CGLIB 动态代理机制3.2.1. 介绍3.2.2. CGLIB 动态代理类使用步骤3.2.3. 代码示例 3.3. JDK 动态代理和 CGLIB 动态…