java对象克隆和面向对象的设计原则

news2024/10/2 8:26:34

java进阶

    • 注解
      • 内置注解
      • 元注解
      • 自定义注解
    • 对象克隆
      • 浅克隆
      • 深克隆
    • java设计模式
      • 建模语言
        • 类之间的关系
        • 依赖关系
        • 关联关系
          • 单向关联
          • 双向关联
          • 自关联
        • 聚合关系
        • 组合关系
        • 继承关系
        • 实现关系
    • 面向对象设计原则
      • 单一职责
      • 开闭原则
      • 里氏替换原则
      • 依赖倒置
      • 接口隔离
      • 迪米特原则
      • 组合/聚合复用原则

注解

java注解又叫java标注,Java 语言中的类、方法、变量、参数和包等都可以被标注。

java注解,可以通过反射来获取注解内容,可以在编译期间使用,也可以被编译到字节码文件中,运行时生效.支持自定义注解

内置注解

java已经定义好的注解,比如

@Override:重写方法注解

@Deprecated:标记过时注解

@SuppressWarnings - 指示编译器去忽略注解中声明的警告。

@FunctionalInterface 用于指示被修饰的接口是函数式接口

元注解

元注解是由java API提供的,用于修饰注解,比如:

@Retention - 标识这个注解怎么保存,是只在代码中,还是编入 class 文件中,或者是在运行时可以通过反射访问。

@Documented - 标记这些注解是否包含在用户文档中。

@Target - 标记这个注解应该是哪种 Java 成员。

@Inherited - 标记这个注解是继承于哪个注解类(默认注解并没有继承于任何子类)

@Repeatable - 标识某注解可以在同一个声明上使用多次。

重点:@Target - 标记这个注解应该是哪种 Java 成员。

ElementType.TYPE 可以应用于类的任何元素。
ElementType.CONSTRUCTOR 可以应用于构造函数。
ElementType.FIELD 可以应用于字段或属性。
ElementType.LOCAL_VARIABLE 可以应用于局部变量。
ElementType.METHOD 可以应用于方法级注释。
ElementType.PACKAGE 可以应用于包声明。
ElementType.PARAMETER 可以应用于方法的参数

@Retention:@Retention 定义了该注解被保留的时间长短,用于注解的生命周期

1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在 class 文件中有效(即 class 保留)
3.RUNTIME:在运行时有效(即运行时保留)

自定义注解

1.自定义注解

@Target(ElementType.FIELD)//作用在类的属性上
@Retention(RetentionPolicy.RUNTIME)//运行时生效
public @interface NotNull {
  //定义注解属性
	String message() default "";
	
	int length() default 0;
	
	String lengthmessage() default "";
}

2.使用自定义注释

@NotNull(message="姓名不能为空",length=3,lengthmessage="长度不能小于3")
	private String name;

3.解析注释

             User user = new User();
		      user.setName("jiim");

          //反射解析注解
		  Field[] fields = user.getClass().getDeclaredFields();//获取所有的属性
          
		  for (Field field : fields) {
		  	        //获取属性的注解
	            NotNull notNull = field.getAnnotation(NotNull.class);
	            if (notNull != null) { 
	                Method m = user.getClass().getMethod("get" + getMethodName(field.getName()));
	                Object value=m.invoke(user);//调用get方法 获取属性值
                    //name值为空,抛出异常
	                if (value==null) {
	                    System.err.println(field.getName() +notNull.message());
	                    throw new NullPointerException(notNull.message());
	                }else{
                        //判断name值的长度
	                	if(String.valueOf(value).length()<(notNull.length())){
	                		 System.err.println(field.getName() +notNull.lengthmessage());
	                	}
	                }
	            }
	        }

对象克隆

对象克隆是指创建一个新的对象,新的对象拥有之前对象内容。

如何是实现克隆

实现Cloneable接口,重写Object类中的clone方法就可以实现克隆,克隆分为浅克隆和深克隆,浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复值

浅克隆

浅克隆克隆值类型的成员变量克隆的是值,克隆引用类型的成员变量克隆的是对象地址。

   //重写clone方法
   @Override
    protected Person clone() throws CloneNotSupportedException {
        Person person = (Person)super.clone();
        return person;
    }
        Person p1 = new Person(100,"jim");
        Person p2 =p1.clone();//克隆的新对象

实现方式:
1.在 Java 语言中,通过覆盖 Object 类的 clone()方法可以实现浅克隆。
2.在 spring 框架中提供 BeanUtils.copyProperties(source,target);
在这里插入图片描述

深克隆

深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。

实现方式:

  1. 类 实现Cloneable接口, 重写Object中的clone方法.(在多级关联时,处理起来比较麻烦)
//Address对象中重写clone方法
@Override
    protected Address clone() throws CloneNotSupportedException {
        return (Address)super.clone();
    }
    //重写Person对象的clone方法
    @Override
    protected Person clone() throws CloneNotSupportedException {
        Person person = (Person)super.clone();
        person.address = (Address)address.clone();   //深度复制  联同person中关联的对象也一同克隆.
        return person;
    }

2.使用序列化方式,可以重写创建对象,包含关联的对象。

/**
     * 自定义克隆方法
     * @return
     */
    public Person myclone() {
            Person person = null;
              try { // 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝
                     ByteArrayOutputStream baos = new ByteArrayOutputStream();
                      ObjectOutputStream oos = new ObjectOutputStream(baos);
                      oos.writeObject(this);
            // 将流序列化成对象
                    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                     ObjectInputStream ois = new ObjectInputStream(bais);
                     person = (Person) ois.readObject();
                  } catch (IOException e) {
                     e.printStackTrace();
                  } catch (ClassNotFoundException e) {
                     e.printStackTrace();
                 }
             return person;
          }

在这里插入图片描述

解决多层克隆问题:我们可以用序列化的方式来实现对象的深克隆,来解决多层克隆的问题

java设计模式

软件设计模式,又称设计模式,它是被反复使用、代码设计经验的总结。它描述了在软件过程中重复发生的问题,以及该问题的解决方案。

设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。

优点:提高程序员的思维能力、编程能力和设计能力

​ 使程序设计更加标准化、提高软件开发效率

​ 设计的代码重用性高、可读性强、可维护性强

建模语言

统一建模语言(UML)是一种用于软件系统分析和设计的语言工具。

UML图:通过不同的图形和符号,来描述软件模型以及各个元素之间的关系

类图(Class diagram)是一种静态的结构图,描述了系统的类的集合,类的属性和类之间的关系。类图是系统分析和设计阶段的重要产物。

在这里插入图片描述

类之间的关系

在软件系统中,类不是孤立存在的,类与类之间存在各种关系。根据类与类之间的耦合度从弱到强排列,UML 中的类图有以下几种关系:依赖关系、关联关系、聚合关系、组合关系、泛化关系和实现关系。其中泛化和实现的耦合度相等,它们是最强的。

依赖关系

依赖关系是一种使用关系,它是对象之间耦合度最弱的一种关联方式,是临时性的关联。在代码中,某个类的方法通过局部变量、方法的参数或者对静态方法的调用来访问另一个类(被依赖类)中的某些方法来完成一些职责。
在 UML 类图中,依赖关系使用带箭头的虚线来表示,箭头从使用类指向被依赖的类。下图所示是人与手机的关系图,人通过手机的语音传送方法打电话。

在这里插入图片描述

关联关系

关联关系是对象之间的一种引用关系,用于表示一类对象与另一类对象之间的联系,如老师和学生、师傅和徒弟等。关联关系是类与类之间最常用的一种关系,分为一般关联关系、聚合关系和组合关系。

关联又可以分为单向关联,双向关联,自关联

单向关联

在这里插入图片描述

在 UML 类图中单向关联用一个带箭头的实线表示。上图表示每个顾客都有一个地址,这通过让 Customer 类持有一个类型为 Address

双向关联

在这里插入图片描述

从上图中我们很容易看出,所谓的双向关联就是双方各自持有对方类型的成员变量。上图中在 Customer 类
中维护一个 List,表示一个顾客可以购买多个商品;在 Product 类中维护一个 Customer 类型的成员变量表示这个产品被哪个顾客所购买

自关联

在这里插入图片描述

自关联在 UML 类图中用一个带有箭头且指向自身的线表示。上图的意思就是Node 类包含类型为 Node 的成员变量,也就是“自己包含自己”。

聚合关系

聚合关系是关联关系的一种,是强关联关系,是整体和部分之间的关系。聚合关系也是通过成员对象来实现的,其中成员对象是整体对象的一部分,但是成员对象可以脱离整体对象而独立存在。例如,学校与老师的关系,学校包含老师,但如果学校停办了,老师依然存在。

在这里插入图片描述

组合关系

组合表示类之间的整体与部分的关系,但它是一种更强烈的聚合关系。在组合关系中,整体对象可以控制部分对象的生命周期,一旦整体对象不存在,部分对象也将不存在,部分对象不能脱离整体对象而存在。例如,头和嘴的关系,没有了头,嘴也就不存在了
在这里插入图片描述

继承关系

继承关系是对象之间耦合度最大的一种关系,表示一般与特殊的关系,是父类与子类之间的关系,是一种继承关系,是 is-a 的关系

在这里插入图片描述

实现关系

实现关系是接口与实现类之间的关系。在这种关系中,类实现了接口,类中的操作实现了接口中所声明的所有的抽象操作。

在这里插入图片描述

面向对象设计原则

单一职责

单一职责原则是最简单的面向对象设计原则,它用于控制类的粒度大小。简单来说,就是一个类只负责一个功能领域中的职责。

优点:低耦合、高内聚。

开闭原则

开闭原则即扩展开发,对修改封闭,简单来说就是在项目种增加新的业务功能时,不会修改原来的代码,而是通过增加类的方式来是实现新的业务功能。抽象化是开闭原则的关键。

在这里插入图片描述

优点:提高了可复用性可维护性

里氏替换原则

定义:所有使用父类的地方必须能透明地使用其子类对象,简单来说就是使用父类地地方子类也能使用。

所以遵循里氏替换原则时,子类继承父类时,不能重写父类的方法。

作用:是实现开闭原则的重要方式之一,克服了继承种重写父类方法造成的可复用性变差的缺点,降低需求变更时引入的风险。

依赖倒置

依赖倒置原则定义:上层模块不应该依赖底层模块,它们都应该依赖于抽象。简单来说就是要求对抽象进行编程,不要对实现进行编程。

在这里插入图片描述

接口隔离

使用多个接口,而不使用单一的总接口,不强迫新功能实现不需要的方法。

迪米特原则

迪米特原则又叫做最小知识原则,它要求一个对象应该对其他对象有最少的了解。只和你的直接朋友交谈。

直接朋友:

1.类中的成员属性

2.在类中的方法作为参数使用

3.在类中的方法作为返回值类型。

注意事项:

  • 迪米特法则的核心是降低类之间的耦合

  • 从被依赖者的角度来说,尽量将逻辑封装在类的内部,对外除了提供的public 方法,不泄露任何信息

  • 从依赖者的角度来说,只依赖应该依赖的对象

  • 切忌不要为了用而用

组合/聚合复用原则

优先使用组合,使系统更灵话,其次才考虑继承,达到复用的目的

使用继承,为了复用父类中的方法,但是类与类的耦合性高.可以使用关联/依赖,在一个类中达到复用别的类中的方法.

总结

  • 开闭原则:要求对扩展开放,对修改关闭
  • 里氏替换原则:不要破坏继承体系
  • 依赖倒置原则:要求面向接口编程
  • 单一职责原则:实现类职责要单一
  • 接口隔离原则:在设计接口的时候要精简单一
  • 迪米特法则:只与直接的朋友的通信
  • 组合/聚合原则:尽量使用聚合和组合的方式,而不是使用继承

设计原则的核心思想就是为了让程序高内聚,低耦合。

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

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

相关文章

关于ucharts在小程序中的使用

项目添加组件 画图之前&#xff0c;首先需要引入ucharts组件&#xff0c;引入链接https://ext.dcloud.net.cn/plugin?id271。 点击下图中红色方框内容&#xff1a; 导入完成后&#xff0c;与uni其他组件一样&#xff0c;无需引入&#xff0c;直接使用即可。 使用组件 uchar…

jhipster自动生成java代码的方法

一、前言 java springboot后台项目用到了jpa查询数据库&#xff0c;还用到了jhipster&#xff0c;这个东西可以自动生成基础的Controller、Service、Dao、JavaBean等相关代码&#xff0c;减少重复开发。 在此总结下使用方法。 二、jhipster自动生成java代码的方法 1.需要先…

KDHX-8700无线高压核相相序表

一、产品简介 KDHX-8700无线高压核相相序表&#xff08;以下简称“仪器”&#xff09;用于测定三相线相序、检测环网或双电源电力网闭环点断路器两侧电源是否同相。在闭环两电源之前一定要进行核相操作&#xff0c;否则可能发生短路。仪器适用于380V&#xff5e;35kV交流输电线…

JavaScript void

文章目录JavaScript voidjavascript:void(0) 含义href"#"与href"javascript:void(0)"的区别JavaScript void javascript:void(0) 含义 我们经常会使用到 javascript:void(0) 这样的代码&#xff0c;那么在 JavaScript 中 javascript:void(0) 代表的是什么…

RTSP协议交互时TCP/UDP的区别 以及视频和音频的区别 以及H264/H265的区别

经过这几天的调试 一个功能简单的 RTSP服务端已经实现了 支持TCP/UDP 支持H264 H265 支持同时传输 AAC音频 记录下 交互时需要注意的地方 1.OPTIONS 都一样 如下&#xff1a;左箭头内是客户端发给服务端 箭头内是服务端回给客户端 2.DESCRIBE 目前的流是包含视频和AAC音频…

计讯物联环保数采仪TS910在扬尘预警监测解决方案的应用

方案背景 随着我国经济高速发展和城市化进程的加速&#xff0c;城市建设工程规模不断扩大&#xff0c;工程施工给居住区、学校、医院等周边环境带来了巨大的影响&#xff0c;特别是扬尘污染带来的细颗粒物&#xff0c;严重危害到人体健康和大气环境质量。 因此&#xff0c;计…

MVC与MVVM

MVC与MVVM举例说明MVCMVVM两者比较MVC <!DOCTYPE html> <html><head><meta charset"utf-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><title>mvc案例</title><link rel"styleshe…

ChatGPT初体验(一)

ChatGPT初体验&#xff08;一&#xff09; ChatGPT登陆方式 “OpenAI研发的聊天机器人程序&#xff0c;于2022年11月30日发布。ChatGPT是人工智能技术驱动的自然语言处理工具&#xff0c;它能够通过学习和理解人类的语言来进行对话&#xff0c;还能根据聊天的上下文进行互动&…

05- 泰坦尼克号海难生死预测 (机器学习集成算法) (项目五)

Kaggle: 一个数据建模和数据分析竞赛平台sns画柱状图: sns.barplot(datatrain,xPclass,ySurvived)查看数据分布(survived 和 fare): sns.FacetGrid(train,hueSurvived,aspect3) ageFacetsns.FacetGrid(train,hueSurvived,aspect3) ageFacet.map(sns.kdeplot,Fare,shadeTrue) …

血氧仪「上潜」,智能穿戴「下沉」

文|智能相对论作者|沈浪缺货、涨价、一“仪”难求......过去短短的几周&#xff0c;血氧仪市场持续走热&#xff0c;受到前所未有的关注&#xff0c;像鱼跃医疗这样的业内巨头更是赚得盆满钵满&#xff0c;但同时也深陷“发国难财”的舆论泥潭&#xff0c;说来也是唏嘘。尽管目…

linux rancher 清理docker容器磁盘空间

目录说明 /var/lib/docker/containers&#xff1a; 是 Docker 在 Linux 系统上默认存储容器信息的目录。在该目录下&#xff0c;每个运行的 Docker 容器都有一个单独的目录&#xff0c;以容器 ID 命名&#xff0c;其中包含有关该容器的元数据和日志文件。 具体来说&#xff0…

ABAP SALV实现弹出ALV选择

问题场景 需要弹出一个ALV并获取选择的数据 实现思路 跳转屏幕弹出ALV&#xff08;通过SALV&#xff09;弹出ALV&#xff08;通过REUSE_ALV_POPUP_TO_SELECT&#xff09; 实现效果 因为这里需要的是单选&#xff0c;所以没有多选列 实现代码 MODULE sel_zfretype INPUT.…

【代码随想录训练营】【Day15】第六章|二叉树|层序遍历|226.翻转二叉树|101.对称二叉树

层序遍历 题目详细&#xff1a;LeetCode.102 层序遍历与上一节讲的三种遍历方式有所不同&#xff0c;层序遍历是指按从上到下&#xff0c;从左到右的顺序&#xff0c;逐层地遍历二叉树的节点。 从其节点的遍历顺序上观察&#xff0c;我们可以发现其跟广度优先遍历&#xff0…

分布式事务理论基础

事务是数据库执行过程中的一个逻辑单位&#xff0c;由一个有限的数据库操作序列构成。 事务有四个特性&#xff0c;习惯上被称为 ACID 特性&#xff1a; Atomicity(原子性) Consistency(一致性) Isolation(隔离性) Durability(持久性) 本地事物 在系统发展初期&#xff0c…

17.微服务SpringCloud

一、基本概念 Spring Cloud 被称为构建分布式微服务系统的“全家桶”&#xff0c;它并不是某一门技术&#xff0c;而是一系列微服务解决方案或框架的有序集合。它将市面上成熟的、经过验证的微服务框架整合起来&#xff0c;并通过 Spring Boot 的思想进行再封装&#xff0c;屏蔽…

Composer: Unknown package has no name defined

安装chatGPT插件到项目&#xff0c;发现如下提示&#xff0c;更新也是提示&#xff1a; Unknown package has no name defined 目录 问题表现 解决未定义包装库 查看当前项目配置 重装本地类库 1.删除相关文件夹及文件 2.清除缓存 3.执行composer install 问题表现 执行…

SQL中的游标、异常处理、存储函数及总结

目录 一.游标 格式 操作 演示 二.异常处理—handler句柄 格式 演示 三.存储函数 格式 参数说明 演示 四.存储过程总结 一.游标 游标(cursor)是用来存储查询结果集的数据类型,在存储过程和函数中可以使用游标对结果集进行循环的处理。游标的使用包括游标的声明、OPEN、…

ThingsBoard-规则链-check relation

1、概述 今天我主要讲解【check relation】规则节点,顾名思义,这个节点就是检查消息的发起者与其他实体之间的关系是否存在。如果勾了“检查与特定实体的关系”,则必须指定相关实体。否则,规则节点检查是否存在与匹配方向和关系类型标准的任何实体的关系。一般情况,我们都…

C++递归算法回溯思想

文章目录一、最简单的递归问题&#xff08;调用函数后无其他代码、不涉及复杂的回溯思想&#xff09;二、递归函数中的return不是结束整个递归函数哦三、递归(涉及回溯)举例学生的年龄问题&#xff08;递归的执行过程&#xff09;四、涉及较复杂的回溯思想楼梯问题一、最简单的…

Zookeeper (更新中)

目录Zookeeper 概述Zookeeper 的特点Zookeeper 的应用场景Zookeeper的数据结构ZNode数据类型ZNode里面存储的信息Zookeeper的选举机制&#xff08;重要&#xff09;Zookeeper第一次启动选举机制Zookeeper非第一次启动选举机制Zookeeper 底层如何按照请求的先后顺序来处理的Zook…