内部类, Comparable接口, Comparator接口, Cloneable接口 ---java

news2024/11/25 20:20:19

目录

一. 内部类

1.1 静态内部类

1.2 实例内部类

1.3匿名内部类

二. 接口的使用实例 

2.1 Comparable接口

2.2 Comparator接口 ---比较器

2.3 Cloneable接口 

深拷贝浅拷贝 


一. 内部类

当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么这个内部的完整结构最好使用内部类。在 Java 中, 可以将一个类定义在另一个类或者一个方法的内部, 前者称为内部类,后者称为外部类 。内部类也是封装的一种体现。
public class OutClass {
        class InnerClass {
        }
}
// OutClass 是外部类
// InnerClass 是内部类

注:内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件 ,命名格式:外部类名字$内部类名字.class

内部类可以分为四类:

1. 静态内部类

2. 实例内部类

3. 匿名内部类(最常用)

4. 局部内部类 (不常用,不做讲解)

1.1 静态内部类

static修饰的内部成员类称为静态内部类。  

上述代码, 我们可以看到,

1. 在静态内部类中定义的成员变量(方法), 可以是static修饰的,

2. 在静态内部类中的成员方法, 可以直接访问在静态内部类中定义的成员变量(方法)在外部类中定义的static修饰的变量(方法), 但不能直接访问外部类中没有被static修饰的变量

 3. 想要在静态内部类的方法中访问外部类的成员变量, 需要创建一个外部类型的对象, 通过对象去访问.

4. 在外部类中创建一个方法, 在这个方法里面, 可以直接创建静态内部类的对象

5. 在外部类之外, 想要创建静态内部类对象,  不需要先创建外部类对象, 必须通过外部类.  去使用

1.2 实例内部类

即未被 static 修饰的成员内部类。

 

由上述代码, 我们可以得到:

1. 实例内部类中不能定义static修饰的变量(方法) , 如果想定义, 需要加final

 2 . 在外部类中创建一个方法, 在这个方法里面, 可以直接创建实例内部类的对象

 3. 在外部类之外, 想要创建实例内部类对象,  需要先创建外部类对象, 通过外部类对象的引用外部对象. 去创建实例内部类对象

4. 在实例内部类的方法中, 都可直接访问外部类和内部类中的任意访问限定符修饰的成员变量(方法) 

 5. 如果外部类和实例内部类中具有相同名称成员时,优先访问的是内部类自己的,  加this. 还访问自己的.

如果要访问外部类同名成员:外部类名称.this.同名成员名字

或像静态内部类一样, 创建一个外部类对象, 对对象的引用

1.3匿名内部类

我们先看一下什么是匿名对象

 如果以后的场景是, 只是用一次对象, 那么可以使用匿名对象.

使用匿名内部类, 首先我们先创建一个接口

正常情况下我们是这样使用的

而匿名内部类, 可以不用创建类TestA, 直接匿名实现接口, 并对其重写

 或更高阶的写法:

 当然, 也可以匿名new类. 

二. 接口的使用实例 

Java 中内置了一些很有用的接口:

2.1 Comparable接口

定义两个字符串

如何比较两个字符串的大小呢?

显然, 是错误的,java当中, 不可以直接比较引用类型的大小 

那么, 我们就可以借助String类型里面的compareTo()方法进行比较

 按住Ctrl我们点进compareTo发现 :

这个方法是通过重写接口中的方法得来的, 那么我们点进去黄框, 就会发现:

原来String类型, 可以进行字符串的比较, 是因为引用了Comparable这个接口, 然后在类中重写compareTo这个方法实现的

 那么同理, 当我们自定义一个类, 创建两个对象时, 想要比较两个对象的大小, 我们就可以通过implements Comparable<>, 并在类中重写compareTo方法, 根据自己的需求, 自定义要比较的标准.

举例:

我们也可以以姓名为标准进行比较:

 再举例:

定义一个数组, 通过Arrays.sort()对数组进行排序:

运行时我们发现报错:

 原因是, Arrays.sort() 不知道以什么标准进行比较

注意事项: 对于 sort 方法来说, 需要传入的数组的每个对象都是 "可比较" 的, 需要具备 compareTo 这样的能力. 通过重写 compareTo 方法的方式, 就可以定义比较规则.

所以Student类, 需要实现Comparable接口, 并重写compareTo方法 

结果: 

2.2 Comparator接口 ---比较器

比较什么, 就定义一个类, 实现Comparator接口, 重写compare方法, 将比较的对象当做参数传递过去,  非常灵活

 

再如上述对数组排序时, 可以使用Arrays.sort(数组名, 比较器), 这样在比较时, 就会使用比较器的方法进行排序. 

2.3 Cloneable接口 

现在, 我们定义一个对象, 我们想把第一个对象克隆到第二个对象

我们看到, Object类中有clone()方法, 我们想拿过来直接用, 发现:

不允许我们直接用, 我们点进去clone()方法可以看到:

它是被protected修饰的, 我们学过, 在不同包中, 想要访问protected修饰的方法, 必须是在子类中访问, 需要通过super进行访问, 所以我们要对clone方法进行重写. 

利用快捷方法:Alt + Insert

这个方法就被创建好了. 

我们看到:

返回类型是Object,  所以我们要调用这个方法时, 要进行向下转型

后面跟着一串throws CloneNotSupportedException, 这个我们先不管后面讲, 先照抄在main方法后面. 

此时运行我们发现报错:

解决方法:

要实现一个Cloneable接口, 表示此类可以被克隆. 

到此为止, 才算克隆成功. 

我们点进去Cloneable接口可以看到:

 

里面什么也没有, 我们管这种接口叫做空接口/标记接口

一个类实现了空接口/标记接口, 那么表示当前这个类, 是可以被怎么样的, 如实现Cloneable, 表示此类可以被克隆. 

 

深拷贝浅拷贝 

什么是深拷贝浅拷贝呢?

我们看一个例子:

在对象里创建一个对象:

上述代码我们修改了person2中的m的money的值, 理论上来说输出的结果应该为:

person1还是6.6 ,person2被改成9.9 ,但是当我们运行起来后发现:

person1的值也被改了. 

这是为什么呢? 我们画图理解一下:

所以person1, person2修改之前都是6.6. 此时, 两个m都指向同一块空间

所以, 修改money的值, person1和person2都变. 

这就是浅拷贝, 只拷贝了原来的对象, 但对象里的对象没有被拷贝. 

那么同理:深拷贝是指完全克隆出一个独立于原来的对象的对象 

那么, 上述代码, 如果想要达到深拷贝效果, Money这个类必须也是一个可以拷贝的类, 所以Money类要实现Cloneable接口, 并重写父类中的clone方法.

这样我们就做好了准备工作, 但是在哪里怎么调用这个方法呢?

在Person的clone()里:

 

 

 

此时person1的m 和person2的m 是两个独立的对象, 相互不耽误. 所以, 修改person2的m的money的值, person1不变, person2变.

完整代码如下:

class Money implements Cloneable{
    public double money = 6.6;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person implements Cloneable{
    public String name;
    public Money m;
    public Person(String name) {
        this.name = name;
        m=new Money();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
       Person tmp = (Person) super.clone();
       tmp.m = (Money) this.m.clone();
       return tmp;
    }
}
public class Test2 {
    public static void main(String[] args)throws CloneNotSupportedException{
        Person person1 = new Person("zhangsan");
        Person person2 =(Person) person1.clone();
        System.out.println("person1修改之前:"+person1.m.money);
        System.out.println("person2修改之前:"+person2.m.money);
        person2.m.money = 9.9;
        System.out.println("person1修改之后:"+person1.m.money);
        System.out.println("person2修改之后:"+person2.m.money);
    }
}

可见, 是不是深拷贝, 是要看程序猿实现的怎么样.

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

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

相关文章

从零开始学Go web——第一天

文章目录 从零开始学Go web——第一天一、Go与web应用简介1.1 Go的可扩展性1.2 Go的模块化1.3 Go的可维护1.4 Go的高性能 二、web应用2.1 工作原理2.2 各个组成部分2.2.1 处理器2.2.2 模板引擎 三、HTTP简介四、HTTP请求4.1 请求的文本数据4.2 请求方法4.2.1 请求方法类型4.2.2…

C语言:输出所有“水仙花数”。“水仙花数”是指一个3位数,其各位数字的立方和等于该数本身,如153=1^3 +5^3+3^3

分析&#xff1a; 在主函数 main 中&#xff0c;程序首先定义四个整型变量 m、a、b 和 c&#xff0c;并用于计算和判断水仙花数。然后使用 printf 函数输出提示信息。 接下来&#xff0c;程序使用 for 循环结构&#xff0c;从 100 到 999 遍历所有三位数。对于每个遍历到的数 m…

C#常见的设计模式-创建型模式

引言 在软件开发过程中&#xff0c;设计模式是一种被广泛采用的思想和实践&#xff0c;可以提供一种标准化的解决方案&#xff0c;以解决特定问题。设计模式分为三种类型&#xff1a;创建型模式、结构型模式和行为型模式。本篇文章将重点介绍C#中常见的创建型模式。 目录 引言…

python实现自动刷平台学时

背景 前一阵子有个朋友让我帮给小忙&#xff0c;因为他每学期都要看视频刷学时&#xff0c;一门平均需要刷500分钟&#xff0c;一学期有3-4门需要刷的。 如果是手动刷的话&#xff0c;比较麻烦&#xff0c;能否帮他做成自动化的。搞成功的话请我吃饭。为了这顿饭&#xff0c;咱…

Elasticsearch:什么是非结构化数据?

非结构化数据定义 非结构化数据是指未按照设计的模型或结构组织的数据。 非结构化数据通常被归类为定性数据&#xff0c;可以是人类或机器生成的。 非结构化数据是最丰富的可用数据类型&#xff0c;经过分析后&#xff0c;可用于指导业务决策并在许多其他用例中实现业务目标。…

正则表达式和awk

目录 一、正则表达式 1.正则表达式基本介绍 2.正则表达式分类 3.基本正则表达式分类 4.代表字符 5.表示次数 6.位置锚定 7.分组或其他 8.扩展正则表达式 二、awk 1.语法 2.选项 3.基础用法 4.内置变量 5.条件判断 6.数组 总结&#xff1a;本章主要介绍了正则表…

【C++】map与set

​&#x1f47b;内容专栏&#xff1a;C/C编程 &#x1f428;本文概括&#xff1a;关联式容器的介绍、set、multiset、map、multimap。 &#x1f43c;本文作者&#xff1a;阿四啊 &#x1f438;发布时间&#xff1a;2023.11.27 一、关联式容器的介绍 在之前C的学习之中&#xf…

STM32入门--看门狗

一、独立看门狗简介 STM32F10xxx内置两个看门狗&#xff0c;提供了更高的安全性、时间的精确性和使用的灵活性。两个看门狗设备(独立看门狗和窗口看门狗)可用来检测和解决由软件错误引起的故障&#xff1b;当计数器达到给定的超时值时&#xff0c;触发一个中断(仅适用于窗口型看…

【vue】a-table的斑马纹以及hover样式的修改:

文章目录 一、效果&#xff1a;二、实现&#xff08;以jeecg为例&#xff09;&#xff1a; 一、效果&#xff1a; 二、实现&#xff08;以jeecg为例&#xff09;&#xff1a; // 设置基数行样式 // .ant-table-tbody tr:nth-child(n) { // color: #fff; // }// hover时候每行…

如何使用 Java 在Excel中创建下拉列表

下拉列表&#xff08;下拉框&#xff09;可以确保用户仅从预先给定的选项中进行选择&#xff0c;这样不仅能减少数据输入错误&#xff0c;还能节省时间提高效率。在MS Excel中&#xff0c;我们可以通过 “数据验证” 提供的选项来创建下拉列表&#xff0c;但如果要在Java程序中…

Android应用程序开发实战篇----期末总结1

项目1&#xff08;了解移动电子商务开发&#xff09; 1,任务一&#xff1a;了解移动电子商务 移动电子商务&#xff1a;利用无线终端进行的电子商务活动。 移动电子商务的特点&#xff1a;方便&#xff0c;摆脱时空性&#xff0c;安全&#xff0c;潜在用户规模大&#xff0c;…

loadrunner-关联

loadrunner-关联 文章目录 关联自动关联手动关联手写脚本&#xff0c;关联登录token 关联 关联的作用是将服务器返回的数据保存为参数&#xff0c;后续接口中会用到该参数&#xff0c;当服务器数据发生变更时&#xff0c;脚本中的参数值也同时进行更新。 当脚本中需要服务器返…

Open Feign 源码解析(二) --- 如何发送http请求

Open Feign 源码解析二 如何发送http请求&#xff1f; 如何组件化&#xff1f; 定义接口 public interface Client {Response execute(Request request, Options options) throws IOException; }是否存在已有的方案&#xff1f; 1&#xff09;rest template http client o…

5.9每日一题(幂级数求收敛区间:收敛半径不变的定理)

幂级数逐项求导逐项求积分&#xff08;乘n或者除n&#xff09;&#xff0c;收敛半径不变 幂级数x换成xx0(即平移)&#xff0c;收敛半径不变

手把手教学拥有自己的CLI

随着开发时间的增长&#xff0c;你积累的模版需要管理&#xff0c;不能老是复制粘贴。那么一个小小的cli 可以帮助你这个问题。它是你进行管理分类的管家&#xff0c;替你管理仓库和翻东西。 技术选型 NodeJSTSpnpmunbuild : unbuild 是基于rollup 配置更加单的打包工具chalk :…

【开源】基于Vue.js的无代码动态表单系统的设计和实现

项目编号&#xff1a; S 026 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S026&#xff0c;文末获取源码。} 项目编号&#xff1a;S026&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 动态类型模块2.2 动态文件模块2.3 动…

2023-11-27操作系统---进程—线程—实验

目录 2023-11-27操作系统_进程—线程_实验 5-10&#xff1a; 代码&#xff1a; 运行结果: 5-11 代码&#xff1a; 运行结果&#xff1a;​编辑 2023-11-27操作系统实验 5-10&#xff1a; 代码&#xff1a; #include<unistd.h> #include<stdio.h> #include…

力扣hot100 滑动窗口最大值 单调队列

&#x1f468;‍&#x1f3eb; 题目地址 &#x1f37b; AC code class Solution {public int[] maxSlidingWindow(int[] nums, int k){int n nums.length;int[] res new int[n - k 1]; // 单调递减队列int[] q new int[n];// q数组维护的是元素在 nums 数组对应的下标int…

FFmepg 核心开发库及重要数据结构与API

文章目录 前言一、FFmpeg 核心开发库二、FFmpeg 重要数据结构与 API1、简介2、FFmpeg 解码流程①、FFmpeg2.x 解码流程②、FFmpeg4.x 解码流程 3、FFMpeg 中比较重要的函数以及数据结构①、数据结构②、初始化函数③、音视频解码函数④、文件操作⑤、其他函数 三、FFmpeg 流程1…

史上最细,2个半月从功能进阶自动化测试,进阶指南...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、学习自动化之前…