iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Effective Java 在工作中的应用总结
  • 697
分享到

Effective Java 在工作中的应用总结

2024-04-02 19:04:59 697人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录一  创建和销毁对象篇1  若有多个构造器参数时,优先考虑构造器2  通过私有构造器强化不可实例化的能力二  类和接口篇1  最

一  创建和销毁对象篇

1  若有多个构造器参数时,优先考虑构造器

当类构造包含多个参数时,同学们会选择 JavaBeans 模式。在这种模式下,可以调用一个无参构造器来创建对象,然后调用  setter 方法来设置必要和可选的参数。目前较受欢迎的方法之一如在类上加入 Lombok 提供的@Data注解,来自动生成getter/setterequals 等方法。但是JavaBeans模式无法将类做成不可变(immutable,详见“使可变形最小化”章节)。这就需要开发者自己掌控值的更新情况,确保线程安全等。

推荐:Builder模式

Builder 模式通过 builder 对象上,调用类似 setter 的方法,设置相关的参数(类似 Proto Buffers)。最后,通过调用 build 方法来生成不可变的对象(immutable object)。使用 Builder 模式的方法之一包括在类上加入 Lombok 提供的 @Builder 注解。

应用:API Request & Response

微服务架构中,服务的请求(request)和响应(response)往往包含较多参数。在处理请求的过程中,笔者也常常会担心误操作修改了请求的内容。所以,笔者倾向使用Builder模式。

我们可使用Builder模式来构建该类型对象。在构建过程中,若需要引入额外逻辑(e.g. if-else),可先返回Builder对象,最后再调用build方法。


import lombok.Builder;



@Builder
public class SampleRequest {
    private String paramOne;
    private int paramTwo;
    private boolean paramThree;
}



@Builder
public class SampleResponse {
    private boolean success;
}



public interface SampleFacade {
    Result<SampleResponse> rpcOne(RequestParam<SampleRequest>);
}



public void testRpcOne() {
    SampleRequest request =
          SampleRequest.builder().paramOne("one").paramTwo(2).paramThree(true).build();
    Result<SampleResponse> response = sampleFacade.rpcOne(request);
}

2  通过私有构造器强化不可实例化的能力

有些类,例如工具类(utility class),只包含静态字段和静态方法。这些类应尽量确保不被实例化,防止用户误用。

推荐:私有化类构造器

为了防止误导用户,认为该类是专门为了继承而设计的,我们可以将构造器私有化。


public class SampleUtility {


    public static String getXXX() {
        return "test";
    }  


    
    private SampleUtility() {}
}



public static void main(String[] args) {
    System.out.println(SampleUtility.getXXX());
}

二  类和接口篇

1  最小化类和成员的可访问性

尽可能地使每个类或者成员不被外界访问。

推荐:有的时候,为了测试,我们不得不将某些私有的(private)类、接口或者成员变成包级私有的(package-private)。这里,笔者推荐大家使用 Guava 提供的 @VisiableForTesting 注解,来提示这是为了测试而使可访问级别变为包级私有,放宽了限制。


import com.Google.common.annotations.VisibleForTesting;


@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
String getXXX() {
    return "test";
}

此外,也有小伙伴推荐 PowerMock 单元测试框架PowerMock Mockito 的加强版,可以实现完成对private/static/final方法的Mock(模拟)。通过加入 @PrepareForTest 注解来实现。


public class Utility {


    private static boolean isGreaterThan(int a, int b) {
        return a > b;
    }


    private Utility() {}
}



import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;


@RunWith(PowerMockRunner.class)
@PrepareForTest({Utility.class})
public class UtilityTest {


    @Test
    public void test_privateIsGreaterThan_success() throws Exception {
        
        boolean result = Whitebox.invokeMethod(Utility.class, "isGreaterThan", 3, 2);


        Assertions.assertTrue(result);
    }
}

2  使可变形最小化

不可变类(immutable class)是指类对应的实例被创建后,就无法改变其成员变量值。即实例中包含的所有信息都必须在创建该实例的时候提供,并在对象的生命周期内固定不变。

不可变类一般采用函数(functional)模式,即对应的方法返回一个函数的结果,函数对操作数进行运算但并不修改它。与之相对应的更常见的是过程的(procedure)或者命令式的(imperative)做法。使用这些方法时,将一个过程作用在它们的操作数上,会导致它的状态发生改变。

如在“若有多个构造器参数时,优先考虑构造器”一节中提到,不可变对象比较简单,线程安全,只有一种状态。使用该类的开发者无需再做额外的工作来维护约束关系。另外,可变的对象可以有任意复杂的状态。若 mutator 方法(e.g. update)无详细的描述,开发者需要自行阅读方法内容。笔者经常会花费较多时间弄清楚在某方法内,可变对象的哪些字段被更改,方法结束后会不会影响后续的对象操作。笔者推荐传入不可变对象,基于此用更新的参数创建新的不可变对象返回。虽然会创建更多的对象,但是保证了不可变形,以及更可读性。

推荐:Guava Collection之Immutable类

笔者在日常开发中倾向将 Immutable 类(ImmutableListImmutableSetImmuableMap)和上文提到的函数模式集合,实现mutator 类方法。


import static com.google.common.collect.ImmutableList.toImmutableList;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;



private static final ImmutableMap<String, Integer> SAMPLE_MAP =
    ImmutableMap.of("One", 1, "Two", 2);



public ImmutableList<TestObj> updateXXX(ImmutableList<TestObj> input) {
    return input.stream()
            .map(obj -> obj.setXXX(true))
            .collect(toImmutableList());
}



public void filterXXX(List<TestObj> input) {
    input.forEach(obj -> obj.setXXX(true));
}

三  泛型篇

1  列表优先于数组

数组是协变的(covariant),即SubSuper的子类型,那么数组类型Sub[] 就是Super[] 的子类型;数组是具体化的,在运行时才知道并检查它们的元素类型约束。而泛型是不可变的和可擦除的(即编译时强化它们的类型信息,并在运行时丢弃)。

需要警惕 public static final 数组的出现。很有可能是个安全漏洞!

四  方法篇

1  校验参数的有效性

若传递无效的参数值给方法,这个方法在执行复杂、耗时逻辑之前先对参数进行了校验(validation),便很快就会失败,并且可清楚地抛出适当的异常。若没有校验它的参数,就可能会在后续发生各种奇怪的异常,有时难以排查定位原因。

笔者认为,微服务提供的API request 也应沿用这一思想。即在API 请求被服务处理之前,先进行参数校验。每个request应与对应的request validator 绑定。若参数值无效,则抛出特定的ClientException(e.g. IllegalArgumentException)。

2  谨慎设计方法签名

谨慎地选择方法的名称:

  • 执行某个动作的方法通常用动词或者动词短语命名:createXXXupdateXXXremoveXXXconvertXXXgenerateXXX
  • 对于返回boolean值的方法,一般以 is 开头:isValidisLiveisEnabled

避免过长的参数列表:目标是四个参数,或者更少。

  • 当参数过多时,笔者会使用Pair,Triple或辅助类(e.g. 静态成员类)

public class SampleListener {


    public ConsumeConcurrentlyStatus consumeMessage(String input) {
          SampleResult result = generateResult(input);
        ...
    } 


    private static SampleResult generateResult(String input) {
        ...
    }


    
    private static class SampleResult {
        private boolean success;
        private List<String> xxxList;
        private int count;
    }
}

3  返回零长度的数组或者集合,而不是null

若一个方法返回 null 而不是零长度的数组或者集合,开发者需要加入 != null 的检查,有时容易忘记出错,报NullpointerException

说到此,笔者想额外提一下 Optional网络上有很多关于 Optional null 的使用讨论。Optional 允许调用者继续一系列流畅的方法调用(e.g. stream.getFirst().orElseThrow(() -> new MyFancyException()))。以下为笔者整理的观点。



public Optional<Foo> findFoo(String id);



public Foo doSomething(String id, Optional<Bar> barOptional);



public class Book {
    private List<Pages> pages;
    private Optional<Index> index;
}



List<Optional<Foo>>

五  通用程序设计篇

1  如果需要精确的答案,请避免使用float和double

float double 类型主要用于科学工程计算。它们执行二进制浮点运算,为了在数值范围上提供较为精准的快速近似计算。但是,它们并不能提供完全精确的结果,尤其不适合用于货币计算。float 或者 double 精确地表示0.1 是不可行的。

若需系统来记录十进制小数点,可使用BigDecimal

2  基本类型优先于装箱基本类型

基本类型(primitive)例如 intdoublelong boolean。每个基本类型都有一个对应的引用类型,称作装箱基本类型(boxed primitive),对应为IntegerDoubleLong Boolean。如书中提到,它们的区别如下:



public int sum(int a, int b) {
    return a + b;
}



public Integer sum(Integer a, Integer b) {
    return a + b;
}

若无特殊的使用场景,推荐总是使用基本类型。若不得不使用装箱基本类型,注意 == 操作和 NullPointerException 异常。装箱基本类型的使用场景:

  • 作为集合中的元素(e.g. Set<Long>)
  • 参数化类型(e.g. ThreadLocal<Long>)
  • 反射的方法调用

六  异常

1  每个方法抛出的异常都要有文档

始终要单独地声明受检的异常,并且利用Javadoc@throws标记,准确地记录下抛出每个异常的条件。

在日常工作中,笔者调用其他组的 API 时,有时会发现一些意料之外的异常。良好的文档记录,可以帮助 API 调用者更好得处理相关的异常。文档记录可包括:异常的类型,异常的 error code,和描述。

2  其他

一些公司将 API 产生的异常分成 ClientException ServerException。一般 ClientException (e.g. 无效的服务 request ) 是由调用方非常规调用 API 导致的异常处理,可不在服务端主要的异常监测范围中。而 ServerException(e.g. 数据库查询超时)是由服务端自身原因导致的问题,平时需要着重监测。

 引用:

Bloch, Joshua. 2018. Effective Java, 3rd Edition

NPM镜像站全新上线:

阿里云开源镜像站是由阿里云提供的开源组件、开源操作系统等工具镜像站。NPM镜像站全新上线,提高开发效率,让您的构建更加迅速。

到此这篇关于Effective Java 在工作中的应用总结的文章就介绍到这了,更多相关Effective Java 的应用内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Effective Java 在工作中的应用总结

本文链接: https://www.lsjlt.com/news/136179.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Effective Java 在工作中的应用总结
    目录一  创建和销毁对象篇1  若有多个构造器参数时,优先考虑构造器2  通过私有构造器强化不可实例化的能力二  类和接口篇1  最...
    99+
    2024-04-02
  • 在Java中Scanner的用法总结
    最近在做OJ类问题的时候,经常由于Scanner的使用造成一些细节问题导致程序不通过(最惨的就是网易笔试,由于sc死循环了也没发现,导致AC代码也不能通过。。。),因此对Scanne...
    99+
    2024-04-02
  • Java各种锁在工作中使用场景和细节经验总结
    目录1、synchronized1.1、共享资源初始化2、CountDownLatch2.1、场景2.2、实现3、总结1、synchronized synchronized 是可重入...
    99+
    2024-04-02
  • Modbus在Java中使用总结
    一、什么是Modbus Modbus是一种串行通信协议,是Modicon公司于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus是工业领域通信协议的业界标准,是工业电子设备之间常用的连接方式Modbus就是...
    99+
    2023-09-13
    网络 modbus java Modbus Poll Netty
  • Java常用工具类总结
    目录一、线程协作、控制并发流程的工具类二、CountDownLatch倒计时门闩三、Semaphore信号量四、Condition接口(又称条件对象)五、CyclicBarrier和...
    99+
    2024-04-02
  • python 3 在工作中的应用
    Python 3在工作中的使用 安装配置Python 3 在notepad++中配置Python 3 使用sql server数据库 操作Excel 发送email python 3 使用日志   安装配置Python 3 安装 ...
    99+
    2023-01-31
    在工作中 python
  • Java中的常用类总结
    这篇文章主要讲解了“Java中的常用类总结”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中的常用类总结”吧!目录Java常用类包装类包装类中的常量包装类的构造方法包装类中的常用方法M...
    99+
    2023-06-20
  • 一名 IT 工程师的九年工作总结!
    与程序打交道的人生,是简单的人生一次做规划局的项目,规划局的职员很是钦佩地说:“你们真了不起,在电脑上敲敲键盘就能做出软件来。”规划局领导说:“跟电脑打交道是最简单的,难的是跟人打交道。”领导的话很有深意,一语道破了本质,做程序的人,是比较...
    99+
    2023-06-02
  • 在Java中Collection的一些常用方法总结
    Java中Collection的常用方法 1、add() 向中添加元素 add(100) 自动装箱操作,实际上是放进去的一个对象, Integer n = new Integer(...
    99+
    2024-04-02
  • 智能财务在工作中的应用
    简介 随着科技的不断发展,智能化技术已经渗透到了各个领域,包括财务管理。智能财务作为一种新兴的技术,在工作中扮演着越来越重要的角色。本文将探讨智能财务在工作中的应用,并举例说明其在不同场景下的作用。智能财务的应用场景1. 财务数据处理和分析...
    99+
    2024-01-20
    在工作中 财务 智能
  • Java中的Object类用法总结
    目录1.Object类是什么?2.Object类中的equals方法3.Object类中的hashCode方法4.编译器自动生成equals和hashCode总结1.Object类是...
    99+
    2023-05-17
    java的object类型 java中的object类 java object类有哪些方法
  • 高效工作的秘诀——Doit.im使用总结报告
    Doit.im是一款高效工作的任务管理工具,可以帮助用户更好地组织和跟踪任务,并提高工作效率。以下是我对Doit.im使用总结报告的...
    99+
    2023-09-28
    Doit.im
  • 在java中session的工作原理
    java中session的工作原理:在创建Session对象时,会有一个SESSION ID,它是唯一的、不重复的、不容易找到规律的字符串。在创建Session对象时,同时创建一个特殊的Cookie对象,并且会将这个特殊的Cookie对象携...
    99+
    2024-04-02
  • Java中的引用知识点总结
    本篇内容介绍了“Java中的引用知识点总结”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!强引用:默认情况下,对象采用的均为强引用(这个对象的...
    99+
    2023-06-05
  • python中numpy 常用操作总结
    前言: NumPy 是 Python 语言的一个扩充程序库,支持大量高维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。同时NumPy 是机器学习必不可少的工具之一。 常用...
    99+
    2024-04-02
  • Java常用时间工具类总结(珍藏版)
    目录常量介绍相关方法工具类源码肝了两天,重新整理了下时间工具类,以后我就以该时间工具类进行项目开发了,后会不定期更新功能,也欢迎留言需求,让工具类不断的完善。 常量介绍 相关方法 ...
    99+
    2024-04-02
  • Vue项目中常用的工具函数总结
    目录前言一、自定义聚焦指令1、方式一2、方式二3、方式三二、输入框防抖1、需求2、思路3、代码实现三、关键字高亮1、需求2、思路3、代码演示四、格式化Excel表格中存储的时间1、需...
    99+
    2024-04-02
  • java中Callback简单使用总结
    1、什么是Callback,什么时候需要使用Callbackcallback是回调的意思,一般我们需要2个类需要相互掉用,一个类把数据动态传递给另外一个类的时候,可以用这种方式,比如Android里面的Launcher类和LauncherM...
    99+
    2023-05-31
    java callback ava
  • Java中常用占位符总结
    Java中占位符指的是在字符串中预留一些特殊标记,用于将变量的值动态的插入到字符串中 %s : 字符串占位符,用于插入字符串类型的值 String name = "Kristen";String str = String.format("H...
    99+
    2023-10-26
    java python 开发语言
  • Java中String类的常用方法总结
    目录概述特点使用步骤常用方法判断功能的方法获取功能的方法转换功能的方法分割功能的方法概述 java.lang.String 类代表字符串。Java程序中所有的字符串文字(例如&quo...
    99+
    2022-11-13
    Java String类常用方法 Java String类 方法 Java String类
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作