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

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

2.4.5 getter 与setter

      在实例方法中有一类特殊的方法,即getter 与setter 方法,它们一般不包含任何业务逻辑,仅仅是为类成员属性提供读取和修改的方法,这样设计有两点好处:

(1)满足面向对象语言封装的特性。尽可能将类中的属性定义为private,针对属性值的访问与修改需要使用相应的getter 与setter 方法,而不是直接对public 的属性进行读取和修改。

(2)有利于统一控制。虽然直接对属性进行读取、修改的方式和使用相应的getter 与setter 方法在效果上是一样的,但是前者难以应对业务的变化。例如,业务要求对某个属性值的修改要增加统一的权限控制,如果有setter 作为统一的属性修改方法则更容易实现,这种情况在一些使用反射的框架中作用尤其明显。

      因此,在类成员属性需要被外部访问的类中,getter 与setter 方法是必备的。除特殊情况需要增加业务逻辑外,它们仅仅是对成员属性的访问和修改操作,其承载的信息价值比较低,所以,建议在类定义中,类内方法定义顺序依次是:公有方法或保护方法 > 私有方法 > getter/setter 方法。

      最典型的getter 与setter 方法使用是在POJO(Plain Ordinary Java Object,简单的Java 对象)类中。在本书中,POJO 专指只包含getter、setter、toString 方法的简单类,常见的POJO 类包括DO(Dada Object)、 BO(Business Object)、DTO(Data Transfer Object)、VO(View Object)、AO(Application Object)。POJO 作为数据载体,通常用于数据传输,不应该包含任何业务逻辑。因此,在POJO 类中,getter 与setter不但是重要的组成部分,更是与外界进行信息交换的桥梁。getter 与setter 方法定义参考示例如下:

public class TicketDO {

      private Long id;

      // 目的地

      private String destination;

      // getter 方法,要求:直接返回相应属性值,不增加业务逻辑

      public Long getId() {

             return id;

      }

      public String getDestination() {

             return destination;

      }

      // 参数名称与类成员变量名称一致,定义中this. 成员名= 参数名,尽量不增加业务逻辑

      public void setId(Long id) {

             this.id = id;

      }

      public void setDestination(String destination) {

             this.destination = destination;

      }

}

      getter 与setter 方法的定义非常简单,正因如此,工程师们会放松对它们的警惕,导致在实际应用中因为不当操作出现问题。下面来罗列那些易出错的getter 与setter方法定义方式:

(1) getter/setter 中添加业务逻辑。问题出现时,程序员的惯性思维会忽略getter/setter 方法的嫌疑,这会增加排查问题的难度。如下示例代码,在getData() 中增加了逻辑判断,修改了原属性值,如出现属性值不一致的情况,这里可能会是程序员最后被排查到的地方。

public Integer getData() {

      if (condition) {

          return this.data + 100;

      } else {

          return this.data - 100;

      }

}

(2)同时定义isXxx() 和getXxx()。在类定义中,两者同时存在会在iBATIS、JSON 序列化等场景下引起冲突。比如,iBATIS 通过反射机制解析加载属性的getter方法时,首先会获取对象所有的方法,然后筛选出以get 和is 开头的方法,并存储到类型为HashMap 的getMethods 变量中。其中key 为属性名称,value 为getter 方法。因此isXxx() 和getXxx() 方法只能保留一个,哪个方法被后存储到getMethods 变量中,就会保留哪个方法,具有一定的随机性。所以当两者定义不同时,会导致误用,进而产生问题。

      与此相关的某个故障中,负责故障回顾的同事在内网发了一篇贴子,标题为“珍爱生命,远离有毒getter”,即在某个POJO 类中,Boolean 属性既有getXxx(),又有isXxx()。isXxx() 的逻辑存在错误,在修复故障时,想当然地在getXxx() 方法中进行修正,但无法修复故障,因为事实上调用的是isXxx()。排查了完整的调用链路,问题才回到POJO 类本身上。这个过程花费了大量的排查精力和故障处理的宝贵时间。

(3)相同的属性名容易带来歧义。在编程过程中,应该尽量避免在子父类的成员变量之间、不同代码块的局部变量之间采用完全相同的命名。虽然这样定义是合法的,但是要避免。这样使用非常容易引起混淆,在使用参数时,难以明确属性的作用域,最终难以分清到底是父类的属性还是子类的属性。扩展开来,对于非setter/getter的参数名称也要避免与成员变量名称相同。

public class ConfusingName {

      public int alibaba;

      // 反例:非setter/getter 方法的参数名称,不允许与本类成员变量同名

      public void get(String alibaba) {

             if(true) {

             final int taobao = 15;

                    ...

             }

             for (int i = 0; i < 10; i++) {

             // 在同一方法体中,不允许与其他代码块中的taobao 命名相同

             final int taobao = 15;

             ...

      }

  }

}

class Son extends ConfusingName {

      // 反例:不允许与父类的成员变量名称相同

      public int alibaba;

}

2.4.6 同步与异步

      同步调用是刚性调用,是阻塞式操作,必须等待调用方法体执行结束。而异步调用是柔性调用,是非阻塞式操作,在执行过程中,如调用其他方法,自己可以继续执行而不被阻塞等待方法调用完毕。异步调用通常用在某些耗时长的操作上,这个耗时方法的返回结果,可以使用某种机制反向通知,或者再启动一个线程轮询。反向通知方式需要异步系统和各个调用它的系统进行耦合;而轮询对于没有执行完的任务会不断地请求,从而加大执行机器的压力。

      异步处理的任务是非时间敏感的。比如,在连接池中,异步任务会定期回收空闲线程。举个现实中的例子,在代码管理平台中,提交代码的操作是同步调用,需要实时返回给用户结果。但是当前库的代码相关活动记录不是时间敏感的,在提交代码时,发送一个消息到后台的缓存队列中,后台服务器定时消费这些消息即可。

      某些框架提供了丰富的异步处理方式,或者是把同步任务拆解成多个异步任务等。


相关文章
|
1天前
|
SQL JavaScript 前端开发
用Java来开发Hive应用
用Java来开发Hive应用
14 7
|
1天前
|
SQL JavaScript 前端开发
用Java、Python来开发Hive应用
用Java、Python来开发Hive应用
11 6
消息中间件 缓存 监控
12 0
|
1天前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
10天前
|
数据采集 Java 数据挖掘
Java IO异常处理:在Web爬虫开发中的实践
Java IO异常处理:在Web爬虫开发中的实践
|
12天前
|
数据采集 存储 前端开发
Java爬虫开发:Jsoup库在图片URL提取中的实战应用
Java爬虫开发:Jsoup库在图片URL提取中的实战应用
|
16天前
|
存储 搜索推荐 Java
探索安卓开发中的自定义视图:打造个性化UI组件Java中的异常处理:从基础到高级
【8月更文挑战第29天】在安卓应用的海洋中,一个独特的用户界面(UI)能让应用脱颖而出。自定义视图是实现这一目标的强大工具。本文将通过一个简单的自定义计数器视图示例,展示如何从零开始创建一个具有独特风格和功能的安卓UI组件,并讨论在此过程中涉及的设计原则、性能优化和兼容性问题。准备好让你的应用与众不同了吗?让我们开始吧!
|
17天前
|
小程序 JavaScript Java
【资料】阿里Java开发手册
本文是关于分享阿里Java开发手册资源及促进编程规范学习的指南。作者以个人经历引入,讲述了公司领导通过细致讲解阿里Java开发手册,提升了团队对代码质量和编程规范的认识
239 0
【资料】阿里Java开发手册
|
23天前
|
IDE Java 开发工具
快速上手指南:如何用Spring Boot开启你的Java开发之旅?
【8月更文挑战第22天】Spring Boot由Pivotal团队开发,简化了Spring应用的创建过程。本文详述了从零开始搭建Spring Boot项目的步骤:首先确保安装了新版JDK、Maven/Gradle及IDE如IntelliJ IDEA或Eclipse;接着访问Spring Initializr网站(start.spring.io),选择所需依赖(如Web模块)并生成项目;最后,使用IDE打开生成的项目,添加`@SpringBootApplication`注解及main方法来启动应用。通过这些步骤,即便是新手也能快速上手,专注于业务逻辑的实现。
31 1
|
25天前
|
Java 持续交付 项目管理
Maven是一款基于Apache许可的项目管理和构建自动化工具,在Java开发中极为流行。
Maven是一款基于Apache许可的项目管理和构建自动化工具,在Java开发中极为流行。它采用项目对象模型(POM)来描述项目,简化构建流程。Maven提供依赖管理、标准构建生命周期、插件扩展等功能,支持多模块项目及版本控制。在Java Web开发中,Maven能够自动生成项目结构、管理依赖、自动化构建流程并运行多种插件任务,如代码质量检查和单元测试。遵循Maven的最佳实践,结合持续集成工具,可以显著提升开发效率和项目质量。
36 1