Effective Java 案例分享(八)

news2024/9/29 17:39:11

39、使用注解而不是通过命名规则分类

如果需要对定义class,property,或者method进行分类管理,推荐的做法是使用注解对其添加类别,而不是通过命名规则分类。这里以JUnit为例:
在JUnit 3中,如果要写测试的方法,该方法必须以test开头,否则不会跑该测试用例。这种方式存在以下问题:

  1. 以test开头容易出现拼写错误,例如“test“写成了“tset”;
  2. 无法确认该方法只是专门跑测试用例的方法,可能是某些原因需要方法以test开头;
  3. 没有办法灵活配置测试用例,例如抛出异常则认为测试通过,但是不用写try-catch代码;

为了解决这个问题,在JUnit 4引入了注解@Test,需要测试的方法使用注解标记即可,例如下面的代码,m2不会执行

// Program containing marker annotations
public class Sample {
@Test
public static void m1() { } // Test should pass
public static void m2() { } // no test.
@Test 
public static void m3() {
	// Test should fail
	throw new RuntimeException("Boom");
}

如果期望测试方法抛出指定异常为通过,可以使用ExceptionTest:

// Program containing annotations with a parameter
public class Sample2 {
	@ExceptionTest(ArithmeticException.class)
	public static void m1() { // Test should pass
		int i = 0;
		i = i / i;
	}
	@ExceptionTest(ArithmeticException.class)
	public static void m2() { // Should fail (wrong exception)
		int[] a = new int[0];
		int i = a[1];
	}
	@ExceptionTest(ArithmeticException.class)
	public static void m3() { } // Should fail (no exception)
}

40、坚持使用OVERRIDE注解

如果方法是从父类或者接口继承的方法,一定要使用OVERRIDE标记。使用OVERRIDE好处有以下几点:

  1. 方法分类,方便知道哪些方法是外部要求实现的,哪些是内部要求实现的;
  2. 方法检查,OVERRIDE标记的方法会自动检查方法是否满足要求,例如方法名,参数类型,返回值,避免拼写错误;
  3. 便于维护,无论是父类还是子类修改了OVERRIDE的方法都会有编译报错,提示开发者及时纠正方法变化带来的问题;

41、使用标记接口定义类型

标记接口内部无需要实现的方法,仅仅是通过添加该接口做类型的区分。例如Android SDK自带的Serializable接口,本身没有实现的方法,但是通过此接口标记该Class可以被序列化。除此之后我们也可以自定义标记接口,为Class打上标记。
标记接口的目的是为Class分类,快速识别Class具有哪些特征,实现了哪些功能。如果要为属性和方法添加标记,需要使用注解。

42、lambda和匿名类相比,优先使用lambda

lambda表达式是Java带来的新语法特性,它最大的优点是语法简洁:

// Anonymous class instance as a function object - obsolete!
Collections.sort(words, new Comparator<String>() {
	public int compare(String s1, String s2) {
		return Integer.compare(s1.length(), s2.length());
	}
});

// Lambda expression as function object (replaces anonymous class)
Collections.sort(words,(s1, s2) -> Integer.compare(s1.length(), s2.length()));

lambda表达式虽然语法简洁,但是有一些不足:

  1. lambda语法没有明确参数的类型和返回值类型,造成代码的可读性变差;
  2. lambda表达式this引用的是调用方的对象,而不是匿名类的对象;

所以在以下两种情况下,还是要使用匿名类:

  1. 方法实现比较复杂,一般来说超过3行推荐使用匿名内部类;
  2. 需要使用匿名类的对象,例如this关键字,需要使用匿名内部类;

43、方法引用和lambda相比,推荐使用方法引用

在可以方法引用的情况下会比lambda表达更加简洁:

// lambda表达式
map.merge(key, 1, (count, incr) -> count + incr);
// 方法引用
map.merge(key, 1, Integer::sum);

lambda表达式中的第三个参数是把两个int相加,在这种情况下正好可以使用Integer的sum方法替换,代码更加简洁。除此之外,比较常见的情况还有执行Runnable接口:

// lambda表达式
service.execute(() -> action());
// 方法引用
service.execute(GoshThisClassNameIsHumongous::action)

以下是一张常用的方法引用和lambda表达式替换的情况:
在这里插入图片描述
总结:优先使用方法引用,其他情况使用lambda表达式。

44、多使用功能性interface

功能性interface指的是没有特定含义的接口,仅仅是完成某种功能的通用性interface,他的名称跟具体实现的需求无关,实现方法的名称也是无含义的。例如比较常用的Consumer:

List<String> list = new ArrayList<>();
list.forEach(new Consumer<String>() {
    @Override
    public void accept(String str) {
        
    }
});

Consumer就是一个功能性接口,他的作用就是把功能的实现和对象分离。除此之外还有其他功能性接口:
在这里插入图片描述
Android提供了很多的功能性接口,如果这些不满足开发者的需求也可以自定义,自定义的interface建议使用@FunctionalInterface注解。

45、谨慎的使用Stream

在Java 8中提供了流式api:Stream。
Stream的特点:

  1. Stream管道是懒汉式的,直到调用了结束方法才会开始计算;
  2. Stream的语法是流式语法(类似Builder),使用方便;

Stream使用案例:

// Overuse of streams - don't do this!
public class Anagrams {
	public static void main(String[] args) throws IOException {
		Path dictionary = Paths.get(args[0]);
		int minGroupSize = Integer.parseInt(args[1]);
		try (Stream<String> words = Files.lines(dictionary)) {
			words.collect(groupingBy(word -> word.chars().sorted()
				.collect(StringBuilder::new,(sb, c) -> sb.append((char)StringBuilder::append).toString()))
			.values().stream()
			.filter(group -> group.size() >= minGroupSize)
			.map(group -> group.size() + ": " + group)
			.forEach(System.out::println);
		}
	}
}

从上面的案例可以看出过度使用Stream过导致代码的可读性变差,所以在使用中应当注意以下几点:

  1. 科学的命名lambda表达式中的参数名称,提高代码可读性;
  2. 使用有益的方法提高代码的可读性;
  3. 在认为有必要的时候使用Stream,而不是滥用;

在Stream中有事情是要注意的:

  1. 普通的代码块,可以使用本地变量,但是使用lambda变量必须是final的;
  2. 普通的代码块可以使用return,break,continue等关键字改变外部的方法逻辑,但是lambda表达不可以;

在以下情况推荐使用Stream:

  1. 简单的元素转换;
  2. 过滤元素;
  3. 对每一个元素只做简单的操作,例如修改,拼接,计算等等;
  4. 对元素添加到其他集合,例如分组;
  5. 对集合搜索出符合某条件的元素;

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

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

相关文章

100% RNN language model ChatRWKV 相关开源项目

RWKV(读作RwaKuv)借鉴了RNN的移动平均模型&#xff08;MA&#xff09;&#xff0c;将transformer的 O ( T 2 d ) O(T^2d) O(T2d)复杂度降低到 O ( T d ) O(Td) O(Td)&#xff0c;同时保持较好的结果表现。RWKV也是一个开源模型&#xff0c;甚至其介绍主页的html代码都有开源。以…

OpenLayers入门,OpenLayers地图初始化时如何设置默认缩放级别、设置默认地图中心点、最大缩放级别和最小缩放级别以及默认坐标系

专栏目录: OpenLayers入门教程汇总目录 前言 OpenLayers地图初始化时如何设置默认缩放级别、初始化时设置默认地图中心点、设置最大缩放级别和最小缩放级别,超过缩放级别用户无法再放大和缩小,和设置默认坐标系。 二、依赖和使用 "ol": "^6.15.1"使用…

[VRTK4.0]添加一个Curved Pointer

学习目标&#xff1a; 演示如何将 Tilia曲线指针添加到场景&#xff0c;以及如何使用 OpenXR 指针姿势来确保指针方向始终与 OpenXR 控制器的正确方向匹配 流程&#xff1a; 步骤一&#xff1a; 现在我们需要Tilia包&#xff0c;所以我们转到窗口Tilia包导入器&#xff0c;既…

【电源专题】电量计参数RSOC/RM/FCC定义

在文章【电源芯片】电量计(Gauge)介绍中我们讲到电量计的功能就是监测电池、计量电量。 那么电量计其实也是有很多算法的,比如【电源专题】电量计估计电池荷电状态方法(开路电压法及库仑计法)的差别文章所说的开路电压法和库仑计法。当然还有如阻抗跟踪法、CEDV算法等。 …

node.js的优点

提示&#xff1a;node.js的优点 文章目录 一、什么是node.js二、node.js的特性 一、什么是node.js 提示&#xff1a;什么是node.js? Node.js发布于2009年5月&#xff0c;由Ryan Dahl开发&#xff0c;是一个基于ChromeV8引擎的JavaScript运行环境&#xff0c;使用了一个事件驱…

The Sandbox 归属周活动第二弹

邀请所有玩家在「归属谷」自由表达自己的想法。 欢迎来到第二届 The Sandbox 归属周&#xff0c;我们很高兴能与您一起庆祝&#xff01; 从 7 月 24 日到 7 月 31 日&#xff0c;我们欢迎所有人参与是次活动&#xff0c;以展示我们全球玩家、创作者、建设者和收藏者社区的独特性…

8款常见的自动化测试开源框架

在如今开源的时代&#xff0c;我们就不要再闭门造车了&#xff0c;热烈的拥抱开源吧&#xff01;本文针对性能测试、Web UI 测试、API 测试、数据库测试、接口测试、单元测试等方面&#xff0c;为大家整理了github或码云上优秀的自动化测试开源项目&#xff0c;希望能给大家带来…

信息安全战线左移!智能网联汽车安全亟需“治未病”

当汽车由典型的工业机械产品逐步发展成为全新的智能移动终端&#xff0c;汽车的安全边界发生了根本性改变&#xff0c;信息安全风险和挑战不断增加。 面对复杂的异构网络、异构系统及车规级特异性要求&#xff0c;智能智能网联汽车信息安全到底要如何防护&#xff0c;已经成为…

优维产品最佳实践第2期:一个“好”的告警通知是怎样的?

告警通知信息是监控实践中非常关键的一环&#xff0c;在众多的告警消息中&#xff0c;如何让管理员快速识别关键信息&#xff0c;从而提升故障响应效率&#xff1f; 本期EasyOps产品使用最佳实践&#xff0c;我们将为您揭晓&#xff1a; 一个称得上”好“的告警通知应该是怎样…

ICC2删除所有电源的方法

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f;知识星球入口 remove_pg_patterns -all remove_pg_strategies -all remove_pg_strategy_via_rules -all remove_pg_via_master_rules -all remove_pg_regions -all remove_routes -net_types {p…

使用Gradio构建生成式AI应用程序; Stability AI推出Stable Diffusion XL 1.0

&#x1f989; AI新闻 &#x1f680; Stability AI推出最先进的AI工具Stable Diffusion XL 1.0 摘要&#xff1a;Stability AI宣布推出Stable Diffusion XL 1.0&#xff0c;该版本是其迄今为止最先进的AI工具。Stable Diffusion XL 1.0提供更鲜艳、更准确的图片生成&#xff…

背包逆推--数字组合

这个题我们进行Y氏DP分析得到&#xff0c;求得的集合为等于m的数量&#xff0c;那么属性就是count(数量) 进行状态计算&#xff0c;一边是关于不选第i个物品的所有方案&#xff0c;一边是关于选第i个物品的方案。 #include<bits/stdc.h> using namespace std; int a[1000…

【数字IC基础】竞争与冒险

竞争-冒险 1. 基本概念2. 冒险的分类3. 静态冒险产生的判断4. 毛刺的消除使用同步电路使用格雷码增加滤波电容增加冗余项&#xff0c;消除逻辑冒险引入选通脉冲 1. 基本概念 示例一&#xff1a; 如上图所示的这个电路&#xff0c;使用了两个逻辑门&#xff0c;一个非门和一个与…

二. 多传感器时间同步方案(时序闭环)--1

前两篇文章讲了器件选型和多传感器系统设计&#xff1a; 一. 器件选型心得&#xff08;系统设计&#xff09;--1_goldqiu的博客-CSDN博客 一. 器件选型心得&#xff08;系统设计&#xff09;--2_goldqiu的博客-CSDN博客 二. 多传感器时间同步方案&#xff08;时序闭环&#x…

选择适合产品需求管理的项目管理系统,打造完美项目流程!

一般来说&#xff0c;互联网产品经理收到的需求一般分为业务需求、用户需求和产品功能需求。业务需求主要包括战略和规则需求&#xff1b;用户需求一般是真实反馈、真实需求、吐槽、建议等。&#xff1b;功能需求主要围绕产品的旧功能问题进行升级&#xff0c;bug处理、技术问题…

高德地图JS API升级到2.0版本

项目上反馈高德地图底图信息更新不及时&#xff0c;不利于进行点位规划。经研究发现高德地图JS API 1.4.15版本相对于2.0版本&#xff0c;确实地图切片上的标注信息较少。通过工单的形式询问高德的技术工程师认识到1.4.15版本数据更新有延迟&#xff0c;1.4.15版本地图的数据以…

深入理解Go语言中的并发编程【29】【原子操作(atomic包)、并发安全性】

文章目录 原子操作(atomic包)原子操作atomic包示例 并发安全性 原子操作(atomic包) 原子操作 代码中的加锁操作因为涉及内核态的上下文切换会比较耗时、代价比较高。针对基本数据类型我们还可以使用原子操作来保证并发安全&#xff0c;因为原子操作是Go语言提供的方法它在用户…

iOS 应用上架的步骤和工具简介

APP开发助手是一款能够辅助iOS APP上架到App Store的工具&#xff0c;它解决了iOS APP上架流程繁琐且耗时的问题&#xff0c;帮助跨平台APP开发者顺利将应用上架到苹果应用商店。最重要的是&#xff0c;即使没有配置Mac苹果机&#xff0c;也可以使用该工具完成一系列操作&#…

C#实现滑动拼图验证码

开发环境&#xff1a;C#&#xff0c;VS2019&#xff0c;.NET Core 3.1&#xff0c;ASP.NET Core 1、建立一个验证码控制器 新建两个方法Create和Check&#xff0c;Create用于创建验证码&#xff08;返回2张图片和令牌&#xff09;&#xff0c;Check用于验证&#xff08;验证图…

EXCEL数据自动web网页查询----高效工作,做个监工

目的 自动将excel将数据填充到web网页,将反馈的数据粘贴到excel表 准备 24KB的鼠标连点器软件(文末附链接)、Excel 宏模块 优势 不需要编程、web验证、爬虫等风险提示。轻量、稳定、安全。 缺点 效率没那么快 演示 宏环境 http://t.csdn.cn/DRAC2 宏按钮