Java构建对象常用3种方法解析

前言

当我们面对具有大量可选成员变量的 Java 类时,创建这些对象的最佳方法是什么?通常有三种方法: 伸缩构造函数,JavaBean模式和构建器模式。

构造函数

UserInfo userInfo1 = new UserInfo("felord.cn", 28);
UserInfo xxxxxx = new UserInfo("felord.cn", "xxxxxx", 28);
UserInfo xxxxxx1 = new UserInfo("felord.cn", "xxxxxx", 28, LocalDateTime.now());

构造函数通常需要可伸缩性,也就是参数列表需要重载。有些时候我不得不传入null进行初始化。

// 不合理的构造使用示范
UserInfo xxxxxx = new UserInfo(null, null, 28);

而且不能直观看出这些参数所代表的的含义,这有可能引发致命的错误,我们将同类型的username和address互换位置依然成功初始化了对象,不会显式的引发构建错误,这是不合理的。

IDEA 参数列表提示功能

另外如果参数列表比较长,有七八个的话,代码是非常冗长的。

难道构造函数一无是处吗,当然不是。胖哥在使用构造参数时会确保构造的参数列表不会太长,而且如果参数是可选的话,不会将其置于构造函数中的。另外构建不可变对象使用构造函数也是极好的。

JavaBean

这种方式是最常用的创建对象的方法。只需要使用无参构造函数,然后为每个成员变量设置setter方法。

UserInfo userInfo = new UserInfo();

userInfo.setUsername("felord.cn");
userInfo.setAge(28);

这种方式之所以使用非常普遍是因为很多知名框架需要你采用这种模式,比如JSON类库Jackson、Spring Framework还有绝大部分的ORM框架。

大多数情况下这种方式是可以胜任的。它的缺点在于我们需要两步来完成对象的创建工作,另外它缺乏创建不可变对象的能力。

构建器

构建器其实在我之前的文章多次用到,Spring Security对HttpSecurity的配置就用到了该模式。构建器不仅获得了伸缩构造函数的安全性,而且可读性更好。

我们需要在目标对象(这里是UserInfo)内部创建了一个静态类,通常简单地称为Builder。Builder声明了一系列方法来设置对象属性的值,然后将其返回Builder本身,完成所有调用后,我们调用Builder的无参build方法进行目标对象的初始化。

public class UserInfo {
  private String username;
  private String address;
  private Integer age;
  private LocalDateTime addTime;

  // 私有化无参构造
  private UserInfo() {
  }

  public static class Builder {
    private String username;
    private Integer age;
    private String address;
    private LocalDateTime addTime;

    public Builder username(String username) {
      this.username = username;
      return this;
    }

    public Builder address(String address) {
      this.address = address;
      return this;
    }

    public Builder age(Integer age) {
      this.age = age;
      return this;
    }

    public Builder addTime(LocalDateTime addTime) {
      this.addTime = addTime;
      return this;
    }

    public UserInfo build() {
      UserInfo userInfo = new UserInfo();

      userInfo.username = this.username;
      userInfo.address = this.address;
      userInfo.age = this.age;
      userInfo.addTime = this.addTime;

      return userInfo;
    }
  }
  // 省略 getter
}

然后初始化对象就可以这么写:

UserInfo userInfo = new UserInfo.Builder()
    .username("felord.cn")
    .address("xxxxxx")
    .age(28)
    .addTime(LocalDateTime.now())
    .build();

这种写法首先很流畅,而且可读性更高,同时灵活度也得到了保证,可选参数更易处理。但是这种模式增加了我们代码的书写难度,需要进行一些额外的定义。当然你可以借助于Lombok框架的@Builder注解来直接使用构建器模式,但是不是每个人都喜欢Lombok。

由于常用的第三方框架的原因,这种写法的使用场景并不是那么宽泛。通常在定义一些配置时使用它。可参考在这篇文章的做法。

总结

在Java日常开发中构造函数和JavaBean是我们最常用的创建对象的手段,构建器的适用场景相对少了一些,但是在定义一些配置的时候还是非常有用的。好了今天就聊到这里,希望对你有所帮助。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2020-09-05

使用maven构建java9 service实例详解

序 本文主要研究下如何在maven里头构建java9 multi module及service实例 maven 整个工程跟传统maven多module的工程结构一样,java9的一个module对应maven project的一个module.下面是根目录下的pom文件: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4

如何理解Java中基类子对象的构建过程从"基类向外"进行扩散的?

<Java编程思想>复用类一章,提出基类的子对象的构建过程是从基类"向外"进行扩散的. 下面通过实例进行讲解,首先看下面的代码: import static net.mindview.util.Print.*; //<java编程思想>提供的类库 /** * @author Administrator * */ public class Cat extends Animal { public Cat() { // TODO Auto-generated cons

Java基于Semaphore构建阻塞对象池

java中使用Semaphore构建阻塞对象池 Semaphore是java 5中引入的概念,叫做计数信号量.主要用来控制同时访问某个特定资源的访问数量或者执行某个操作的数量. Semaphore中定义了一组虚拟的permits,通过获取和释放这些permits,Semaphore可以控制资源的个数. Semaphore的这个特性可以用来构造资源池,比如数据库连接池等. Semaphore有两个构造函数: public Semaphore(int permits) { sync = new No

Java8如何构建一个Stream示例详解

Stream初体验 Stream是Java8中操作集合的一个重要特性,我们先来看看Java里面是怎么定义Stream的: "A sequence of elements supporting sequential and parallel aggregate operations." 我们来解读一下上面的那句话: 1.Stream是元素的集合,这点让Stream看起来用些类似Iterator: 2.可以支持顺序和并行的对原Stream进行汇聚的操作. Stream的创建方式有很多种,除

使用Jenkins Pipeline自动化构建发布Java项目的方法

简介 Pipeline,简而言之,就是一套运行于Jenkins上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排与可视化. Pipeline是Jenkins2.X的最核心的特性,帮助Jenkins实现从CI到CD与DevOps的转变. 一,创建pipeline项目 二,清除部分历史构建 三,参数化构建 这里使用三个参数,分别对应是否拉取代码,项目名称,以及发版选项 四,编写pipeline脚本 选择pipeline script 编写pipelin

详解java构建者模式Builder

定义 Builder模式是一步步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细的控制对象的构建过程.该模式是将构建复杂对象的过程和它的部件解耦,使得构建过程和部件的表示隔离. 作为复杂对象可能有很多组成部分,比如汽车有车轮.方向盘.发动机.变速箱还有各种小零件等,如何将这些部件组装成一台汽车,这个装配的过程漫长且复杂,对于这种情况,为了对外部隐藏实现细节,就可以使用Builder模式将部件和组装过程分离,使得构建过程和部件分离可自由扩展,两者之间的耦合也降到最低

Java构建乘积数组的方法

本文实例为大家分享了Java构建乘积数组的具体实现代码,供大家参考,具体内容如下 给定一个数组A[0,1,-,n-1],请构建一个数组B[0,1,-,n-1],其中B中的元素B[i]=A[0]A[1]-A[i-1]*A[i+1]-*A[n-1]. 不能使用除法. 代码 解法一 暴力法,这是本能就能想到的解决办法. public static int[] multiply(int[] array) { if (array == null) { return null; } int len = ar

Java构建高效结果缓存方法示例

缓存是现代应用服务器中非常常用的组件.除了第三方缓存以外,我们通常也需要在java中构建内部使用的缓存.那么怎么才能构建一个高效的缓存呢? 本文将会一步步的进行揭秘. 使用HashMap 缓存通常的用法就是构建一个内存中使用的Map,在做一个长时间的操作比如计算之前,先在Map中查询一下计算的结果是否存在,如果不存在的话再执行计算操作. 我们定义了一个代表计算的接口: public interface Calculator<A, V> { V calculate(A arg) throws I

Vue自动构建发布脚本的方法示例

简介 使用cross-env, scp2两个插件完成 cross-env cross-env这是一款运行跨平台设置和使用环境变量的脚本. 为什么需要cross-env? NODE_ENV=production 像这样设置环境变量时,大多数Windows命令提示符都会阻塞 .(Windows上的Bash是例外,它使用本机Bash.)同样,Windows和POSIX命令使用环境变量的方式也有所不同.对于POSIX,您可以使用: $ENV_VAR 和在Windows上可以使用 %ENV_VAR% .

Yii 2.0如何使用页面缓存方法示例

前言 本文主要给大家介绍的是关于Yii2.0如何使用页面缓存的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍. 起初使用页面缓存,发现使用于含有参数的方法存在弊端,只能缓存第一次的页面,导致后面所有不同参数的页面均显示第一次缓存页面:没有生成一个参数页面一个缓存:于是,进行了重写页面缓存. 示例代码 <?php namespace common\lib; use Yii; use yii\caching\Cache; use yii\di\Instance; use yii\web\

java统计汉字字数的方法示例

本文实例讲述了java统计汉字字数的方法.分享给大家供大家参考,具体如下: public class TongJiHanZi { public static int count(String text) { String Reg="^[\u4e00-\u9fa5]{1}$";//正则 int result=0; for(int i=0;i<text.length();i++){ String b=Character.toString(text.charAt(i)); if(b.m

Java计算黑洞数的方法示例

本文实例讲述了Java计算黑洞数的方法.分享给大家供大家参考,具体如下: 任意一个5位数,比如:34256,把它的各位数字打乱,重新排列,可以得到一个最大的数:65432,一个最小的数23456.求这两个数字的差,得:41976,把这个数字再次重复上述过程(如果不足5位,则前边补0).如此往复,数字会落入某个循环圈(称为数字黑洞). 比如,刚才的数字会落入:[82962,75933, 63954, 61974]这个循环圈. 请编写程序,找到5位数所有可能的循环圈,并输出,每个循环圈占1行.其中5

java实现合并图片的方法示例

本文实例讲述了java实现合并图片的方法.分享给大家供大家参考,具体如下: package com.test; import java.io.File; import java.awt.image.BufferedImage; import javax.imageio.ImageIO; public class ImageCombineTest { public static void main(String args[]) { try { // 读取第一张图片 File fileOne = n

Python构建XML树结构的方法示例

本文实例讲述了Python构建XML树结构的方法.分享给大家供大家参考,具体如下: 1.构建XML元素 #encoding=utf-8 from xml.etree import ElementTree as ET import sys root=ET.Element('color') #用Element类构建标签 root.text=('black') #设置元素内容 tree=ET.ElementTree(root) #创建数对象,参数为根节点对象 tree.write(sys.stdout

Java实现高效随机数算法的示例代码

前言 事情起源于一位网友分享了一个有趣的面试题: 生成由六位数字组成的ID,要求随机数字,不排重,不可自增,且数字不重复.ID总数为几十万. 初次解答 我一开始想到的办法是 生成一个足够大的ID池(其实就是需要多少就生成多少) 对ID池中的数字进行随机排序 依次消费ID池中的数字 可惜这个方法十分浪费空间,且性能很差. 初遇梅森旋转算法 后面咨询了网友后得知了一个高效的随机数算法:梅森旋转(Mersenne Twister/MT).通过搜索资料得知: 梅森旋转算法(Mersenne twiste

利用shell find命令删除过期的缓存方法示例

前言 最近发现网站的缓存文件过多,达到100G,占据了大量硬盘,但是其实有很多缓存是不需要的,因为文件被访问的次数并不相同.通过查找相关的资料发现最节省硬盘的缓存方式就是只留下2天的缓存,因为一个网站的文件,总被大量访问的就那么几个.下面就来看看详细的解决方法吧. 方法如下 find / -amin -10 # 查找在系统中最后10分钟访问的文件 find / -atime -2 # 查找在系统中最后48小时访问的文件 find / -mmin -5 # 查找在系统中最后5分钟里修改过的文件 f