码出高效:Java开发手册-第2章(5)

简介: 本章开始讲解面向对象思想,并以Java 为载体讲述面向对象思想在具体编程语言中的运用与实践。当前主流的编程语言有50 种左右,主要分为两大阵营:面向对象编程与面向过程编程。面向对象编程(Object-Oriented Programming,OOP)是划时代的编程思想变革,推动了高级语言的快速发展和工业化进程。OOP 的抽象、封装、继承、多态的理念使软件大规模化成为可能,有效地降低了软件开发成本、维护成本和复用成本。面向对象编程思想完全不同于传统的面向过程编程思想,使大型软件的开发就像搭积木一样隔离可控、高效简单,是当今编程领域的一股势不可......

2.3.5 this 与 super

      对象实例化时,至少有一条从本类出发抵达Object 的通路,而打通这条路的两个主要工兵就是this 和super,逢山开路,遇水搭桥。但是this 和super 往往是默默无闻的,在很多情况下可以省略,比如:

  • 本类方法调用本类属性。
  • 本类方法调用另一个本类方法。
  • 子类构造方法隐含调用 super()。

      任何类在创建之初,都有一个默认的空构造方法,它是super() 的一条默认通路。构造方法的参数列表决定了调用通路的选择;如果子类指定调用父类的某个构造方法,super 就会不断往上溯源;如果没有指定,则默认调用super()。如果父类没有提供默认的构造方法,子类在继承时就会编译错误,如图2-4 所示。

4.jpg

图2-4 父类默认构造方法缺失

      如果父类坚持不提供默认的无参构造方法,必须在本类的无参构造方法中使用super 方式调用父类的有参构造方法,如public Son(){ super(123); }。

      一个实例变量可以通过this. 赋值另一个实例变量;一个实例方法可以通过this.调用另一个实例方法;甚至一个构造方法都可以通过this.调用另一个构造方法。如果this 和super 指代构造方法,则必须位于方法体的第一行。换句话说,在一个构造方法中,this和super 只能出现一个,且只能出现一次,否则在实例化对象时,会因子类调用到多个父类构造方法而造成混乱。

      由于this 和super 都在实例化阶段调用,所以不能在静态方法和静态代码块中使用this 和super 关键字。this 还可以指代当前对象, 比如在同步代码块synchronized(this){...} 中,super 并不具备此能力。但super 也有自己的特异功能,在子类覆写父类方法时,可以使用super 调用父类同名的实例方法。最后总结一下this和super 的异同点,如图2-5 所示。

5.jpg

图2-5 this和super的异同点

2.3.6 类关系

      关系是指事物之间存在单向或相互的作用力或者影响力的状态。类与类之间的关系可分成两种:有关系与没关系,这似乎是一句非常正确的废话,难点在于确定类与类之间是否存在相互作用。证明类之间没关系是一个涉及业务、架构、模块边界的问题,往往由于业务模型的抽象角度不同而不同,是一件非常棘手的事情。如果找到了没有关系的点,就可以如庖丁解牛一样,进行架构隔离、模块解耦等工作。有关系的情况下,包括如下6 种类型:

  • 【继承】extends (is-a)。
  • 【实现】implements (can-do)。
  • 【组合】类是成员变量 (contains-a)。
  • 【聚合】类是成员变量 (has-a)。
  • 【依赖】是除组合与聚合外的单向弱关系。比如使用另一个类的属性、方法,或以其作为方法的参数输入,或以其作为方法的返回值输出(depends-a)。
  • 【关联】是互相平等的依赖关系 (links-a)。

      继承和实现是比较容易理解的两种类关系。在架构设计中,要注意组合、聚合、依赖和关联这四者的区别。

      组合在汉语中的含义是把若干个独立部分组成整体,各个部分都有其独立的使用价值和生命周期。而类关系中的组合是一种完全绑定的关系,所有成员共同完成一件使命,它们的生命周期是一样的,极度容易混淆。组合体现的是非常强的整体与部分的关系,同生共死,部分不能在整体之间共享。

      聚合是一种可以拆分的整体与部分的关系,是非常松散的暂时组合,部分可以被拆出来给另一个整体。比如,汽车与轮子之间的关系就是聚合关系,轮子模块包括钢圈、轮胎、气嘴。轮子拆卸下来用到另一个汽车上是完全没有问题的。

      依赖是除组合和聚合外的类与类之间的单向弱关系,就是一个类A 用到类B,那么就说A依赖B,这种关系是偶然的、松散的、临时的。依赖使用另一个类的属性、方法,或以其作为方法的参数输入,或以其作为方法的返回值输出。本书认为,广义上的有向关联也等同于依赖。依赖往往是模块解耦的最佳点。

      关联即是互相平等的依赖关系,可以在关联点上进行解耦,但是解耦难度略大于依赖关系。

      在类图中,用空心的三角形表示继承,用实心的菱形表示组合,用空心的菱形表示聚合,用一条直线表示关联,这四者都是用实线连接的。用三角形来表示实现,用一个箭头表示依赖,与前面的区别是这两者都是用虚线连接的。在画类图时,菱形、箭头、三角形放在哪一侧呢?在很多类图中,这个处理是非常随意的。如果方向画反了,那么类结构的认知也就反了。有一个规律,有形状的图形符号一律放在权力强的这一侧,如表2-3 所示。

      随着业务和架构的发展,类与类的关系是会发生变化的,必须用发展的眼光看待类图。比如表2-3 中的Body 和Head,如果有一天,动物的脑袋可以随意地移植,那么就从组合关系变成聚合关系了。狗与狗绳之间的约束,虽然很弱,但是如果防疫局在狗绳上标记疫苗记录,那么它们之间的关系就会变强,就变成组合关系了。在业务重构过程中,往往会把原来强组合的关系拆开来,供其他模块调用,这就是类图的一种演变。

表2-3 类关系示例图

6.jpg

2.3.7 序列化

      内存中的数据对象只有转换为二进制流才可以进行数据持久化和网络传输。将数据对象转换为二进制流的过程称为对象的序列化(Serialization)。反之,将二进制流恢复为数据对象的过程称为反序列化(Deserialization)。序列化需要保留充分的信息以恢复数据对象,但是为了节约存储空间和网络带宽,序列化后的二进制流又要尽可能小。序列化常见的使用场景是RPC 框架的数据传输。常见的序列化方式有三种:

      (1) Java原生序列化。Java类通过实现Serializable接口来实现该类对象的序列化,这个接口非常特殊,没有任何方法,只起标识作用。Java 序列化保留了对象类的元数据(如类、成员变量、继承类信息等),以及对象数据等,兼容性最好,但不支持跨语言,而且性能一般。

      实现Serializable 接口的类建议设置serialVersionUID 字段值,如果不设置,那么每次运行时,编译器会根据类的内部实现,包括类名、接口名、方法和属性等来自动生成serialVersionUID。如果类的源代码有修改,那么重新编译后serialVersionUID的取值可能会发生变化。因此实现Serializable 接口的类一定要显式地定义serialVersionUID 属性值。修改类时需要根据兼容性决定是否修改serialVersionUID 值:

  • 如果是兼容升级,请不要修改 serialVersionUID 字段,避免反序列化失败。
  • 如果是不兼容升级,需要修改 serialVersionUID 值,避免反序列化混乱。

      使用Java 原生序列化需注意,Java 反序列化时不会调用类的无参构造方法,而是调用native 方法将成员变量赋值为对应类型的初始值。基于性能及兼容性考虑,不推荐使用Java 原生序列化。

      (2)Hessian 序列化。Hessian 序列化是一种支持动态类型、跨语言、基于对象传输的网络协议。Java 对象序列化的二进制流可以被其他语言(如C++、Python)反序列化。Hessian 协议具有如下特性:

  • 自描述序列化类型。不依赖外部描述文件或接口定义,用一个字节表示常用基础类型,极大缩短二进制流。
  • 语言无关,支持脚本语言。
  • 协议简单,比 Java原生序列化高效。

      相比Hessian 1.0,Hessian 2.0 中增加了压缩编码,其序列化二进制流大小是Java序列化的50%,序列化耗时是Java 序列化的30%,反序列化耗时是Java 反序列化的20%。

      Hessian 会把复杂对象所有属性存储在一个Map 中进行序列化。所以在父类、子类存在同名成员变量的情况下,Hessian 序列化时,先序列化子类,然后序列化父类,因此反序列化结果会导致子类同名成员变量被父类的值覆盖。

     (3)JSON 序列化。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。JSON 序列化就是将数据对象转换为JSON 字符串。在序列化过程中抛弃了类型信息,所以反序列化时只有提供类型信息才能准确地反序列化。相比前两种方式,JSON 可读性比较好,方便调试。

      序列化通常会通过网络传输对象,而对象中往往有敏感数据,所以序列化常常成为黑客的攻击点,攻击者巧妙地利用反序列化过程构造恶意代码,使得程序在反序列化的过程中执行任意代码。Java 工程中广泛使用的Apache Commons Collections、Jackson、fastjson 等都出现过反序列化漏洞。如何防范这种黑客攻击呢?有些对象的敏感属性不需要进行序列化传输,可以加transient 关键字,避免把此属性信息转化为序列化的二进制流。如果一定要传递对象的敏感属性,可以使用对称与非对称加密方式独立传输,再使用某个方法把属性还原到对象中。应用开发者对序列化要有一定的安全防范意识,对传入数据的内容进行校验或权限控制,及时更新安全漏洞,避免受到攻击。

相关文章
|
2月前
|
Java API Maven
如何使用Java开发抖音API接口?
在数字化时代,社交媒体平台如抖音成为生活的重要部分。本文详细介绍了如何用Java开发抖音API接口,从创建开发者账号、申请API权限、准备开发环境,到编写代码、测试运行及注意事项,全面覆盖了整个开发流程。
296 10
|
2月前
|
监控 Java API
如何使用Java语言快速开发一套智慧工地系统
使用Java开发智慧工地系统,采用Spring Cloud微服务架构和前后端分离设计,结合MySQL、MongoDB数据库及RESTful API,集成人脸识别、视频监控、设备与环境监测等功能模块,运用Spark/Flink处理大数据,ECharts/AntV G2实现数据可视化,确保系统安全与性能,采用敏捷开发模式,提供详尽文档与用户培训,支持云部署与容器化管理,快速构建高效、灵活的智慧工地解决方案。
|
20天前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
6天前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
1月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
67 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
30天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
116 13
|
1月前
|
算法 Java API
如何使用Java开发获得淘宝商品描述API接口?
本文详细介绍如何使用Java开发调用淘宝商品描述API接口,涵盖从注册淘宝开放平台账号、阅读平台规则、创建应用并申请接口权限,到安装开发工具、配置开发环境、获取访问令牌,以及具体的Java代码实现和注意事项。通过遵循这些步骤,开发者可以高效地获取商品详情、描述及图片等信息,为项目和业务增添价值。
81 10
|
29天前
|
前端开发 Java 测试技术
java日常开发中如何写出优雅的好维护的代码
代码可读性太差,实际是给团队后续开发中埋坑,优化在平时,没有那个团队会说我专门给你一个月来优化之前的代码,所以在日常开发中就要多注意可读性问题,不要写出几天之后自己都看不懂的代码。
62 2
|
1月前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
2月前
|
开发框架 Java 关系型数据库
Java哪个框架适合开发API接口?
在快速发展的软件开发领域,API接口连接了不同的系统和服务。Java作为成熟的编程语言,其生态系统中出现了许多API开发框架。Magic-API因其独特优势和强大功能,成为Java开发者优选的API开发框架。本文将从核心优势、实际应用价值及未来展望等方面,深入探讨Magic-API为何值得选择。
81 2