HoneyMoose
  • 首页
  • Java
  • Jersey
  • Jira
  • Confluence
  • U.S.
    • USRealEstate
    • U.S. Travel
    • H1B
  • 项目和网站
    • CWIKI.US
    • OSSEZ 社区
    • WIKI.OSSEZ.COM
    • BUG.OSSEZ.COM
    • RSS.OSSEZ.COM
Computer Science
Computer Science

AssertJ 的异常(Exception )断言

本页面主要来说说 AssertJ 的异常断言。 概述 在本快速导航中,我们主要来聊聊的 AssertJ 的异常(exception)断言。 有关 AssertJ 的项目,请访问 AssertJ / Fluent assertions for java 页面。     不使用 AssertJ 如果不使用 AssertJ,我们需要先捕获一个异常,然后再在异常中进行断言。 例如下面的伪代码,我们捕获了一个异常,然后再进行判断。 try { // ... } catch (Exception e) { // assertions } 但是,如果程序在执行的时候没有抛出异常,在上面的用例中,测试将会通过。 为了让断言能够被执行,为什么我们还需要手动触发一个异常呢? 使用 AssertJ 在 Java 8 以后的版本,我们可以通过使用 AssertJ 和 lambda 表达式,非常容易的对异常进行断言处理。 使用 assertThatThrownBy() 方法 让我们看看下面的代码将会抛出 IndexOutOfBoundsException 异常: 这是因为我们定义一个 List 的长度是 2 ,但是我们有一行代码将会访问 List 的第 3 个元素,上面的代码必然会抛出一个异常。 assertThatThrownBy(() -> { ArrayList<String> myStringList = new ArrayList<String>(Arrays.asList("Strine one", "String two")); myStringList.get(2); }).isInstanceOf(IndexOutOfBoundsException.class) .hasMessageStartingWith("Index 2"); 需要注意上面的代码片段有可能会抛出一个 lambda 表达式异常。 当然,我们还可以使用 AssertJ 来提供一个链式断言,这个就是为什么我们不使用 Junit 自带断言的原因。 .hasMessageStartingWith("Index 2") .hasMessageContaining("2") .hasMessageEndingWith("length 2") .hasMessageContaining("Index 2") .hasNoCause(); 使用 assertThatExceptionOfType 方法 这个方法与上面使用的方法类似,因为我们知道这个程序执行就会抛出异常,因此我们在程序的最开始就指定了异常: assertThatExceptionOfType(ArithmeticException.class).isThrownBy(() -> { int numerator = 10; int denominator = 0; int quotient = numerator / denominator; }) .withMessageContaining("/ by zero"); 上面的方法,因为我们使用了 0 为除数,因此必定会抛出异常。 在程序最开始的时候我们就断言了这个异常。 使用 assertThatIOException 和其他的一些常用类型 AssertJ 针对 一些常用的异常进行了包装,你可以直接使用这些被包装过的异常: assertThatIOException().isThrownBy(() -> { // ... }); 和其他一些类似的异常: assertThatIllegalArgumentException() assertThatIllegalStateException() assertThatIOException() assertThatNullPointerException() 从断言中将异常分离 可选的,我们可以将异常从断言中进行分离。 分离的办法就是添加一个 when 和 then 逻辑段: // when Throwable thrown = catchThrowable(() -> { int numerator = 10; int denominator = 0; int quotient = numerator / denominator; }); // then assertThat(thrown).isInstanceOf(ArithmeticException.class) .hasMessageContaining("/ by zero"); } 上面的代码首先是抛出异常,然后对抛出的异常再进行断言判断。 结论 在这篇短文中,我们对 AssertJ 是如何进行异常断言的情况进行了简单的介绍,同时讨论了 AssertJ 进行是如何进行异常断言的。   https://www.ossez.com/t/assertj-exception/13988

2022年06月06日 0Comments 31Browse 0Like Read more
Computer Science

理解 Java 中的 NumberFormatException 异常

如果我在 Java 中对字符串和数字直接进行类型转换的话,我们有可能会遇到 NumberFormatException 异常。 介绍 当 Java 在将 String 字符串转换为数字的时候,如果遇到没有办法转换的情况,Java 将会抛出一个 NumberFormatException 异常。 NumberFormatException 这个异常是 Java 中的一个 unchecked 类型异常,因此程序不会被要求强制进行处理。 在本页面中,我们对 NumberFormatException 这个异常进行一些简要说明和我们应该如何避免这个异常。 如何导致 NumberFormatException 异常的 在实际编码过程中,有一些构造方法或者类型转换方法,将会导致这个异常。 对导致这个异常的常见情况,我们在下面的页面中进行一些说明和讨论。 构造函数中 如果我们在构造函数中对不是数字的字符串进行类型转换的话,将会有可能抛出这个异常。 例如我们尝试将一个字符串转换为 Integer 或Double 对象,但是输入的字符串不是数字。 下面 2 个句子将会抛出 NumberFormatException 异常: Integer aIntegerObj = new Integer("one"); Double doubleDecimalObj = new Double("two.2"); 我们如果运行上面的代码,我们可以看到 JDK 将会提示我们没有办法将输入的字符串转换为整数类型。 Exception in thread "main" java.lang.NumberFormatException: For input string: "one" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:580) at java.lang.Integer.<init>(Integer.java:867) at MainClass.main(MainClass.java:11)     上面的构造方法将会抛出无法将字符串转换为数字的异常。 在调用 parseInt() 内部方法的时候将会提示无法转换的错误。 上面的修改也非常简单,这是因为 Java 的 Number API 不能处理字符串导致的,我们只需要将输入的字符串进行调整,保持为数字类型即可。 使用下面的代码就没有问题了。 Integer aIntegerObj = new Integer("1"); Double doubleDecimalObj = new Double("2.2"); 处理非数字类型的方法 与构造方法的错误类似,有些方法在处理的时候也会导致异常。 比如说我们常常会用到的下面的一些方法 par seInt(), parseDouble(), valueOf(), 和 decode() 。 例如,我们尝试进行下面的一些类型的转换的话,我们有可能遇到与上面相同的方法: int aIntPrim = Integer.parseInt("two"); double aDoublePrim = Double.parseDouble("two.two"); Integer aIntObj = Integer.valueOf("three"); Long decodedLong = Long.decode("64403L"); 这个错误与在上面构造方法中出现的错误是相同的。 我们可以简单的按照错误提示修改输入参数就可以了: int aIntPrim = Integer.parseInt("2"); double aDoublePrim = Double.parseDouble("2.2"); Integer aIntObj = Integer.valueOf("3"); Long decodedLong = Long.decode("64403"); 输入字符串参数有一些奇怪字符 另外,不仅仅是输入字符串本身不是数字的问题,有可能输入的字符串可能有一些奇怪的字符,包括有空格,下划线等。 类型转换函数或者构造函数,本身是不会对输入字符串进行处理的。 Short shortInt = new Short("2 "); int bIntPrim = Integer.parseInt("_6000"); 上面我们代码执行的时候也会遇到相同的问题。 例如第一行代码的主要原因就是因为有空格,我们可以首先对空格进行清理。 针对这种情况,我们首先需要对输入的字符串进行格式化处理,处理掉错误的字符。 Short shortInt = new Short("2 ".trim()); int bIntPrim = Integer.parseInt("_6000".replaceAll("_", "")); int bIntPrim = Integer.parseInt("-6000"); 需要注意的是,上面代码中的第 3 行,我们给出的是一个负数。 在 Java 中,负数是允许的,但是你不能使用下划线,你只能使用中划线。 语言特性的数字格式化 这里我们说的语言特性数字格式化主要是因为不同地区和国家对数字的表达方式是不一样的。 例如,在一些国家 “4000,1 ” 可能也会被用来表示一个小数“4000.1”。 如果你不对你的程序进行配置的话,在默认情况下,你还是会得到一个 NumberFormatException 异常,因为我们的程序没有办法处理以逗号表示为小数点: double aDoublePrim = Double.parseDouble("4000,1"); 因此,我们需要让我们的程序明白,这里的逗号是小数点才能避免这个类型转换错误。 例如,我们可以使用 NumberFormat 将数字处理的地区设置为欧洲地区,那么你的程序将不会提示格式字符的错误。 请考察下面的代码,我们设置为法国以后,就可以运行了: NumberFormat numberFormat = NumberFormat.getInstance(Locale.FRANCE); Number parsedNumber = numberFormat.parse("4000,1"); assertEquals(4000.1, parsedNumber.doubleValue()); assertEquals(4000, parsedNumber.intValue()); 最佳实践 让我们来看看有可能导致 NumberFormatException 异常的一些原因,和我们应该如何来应对: Java Number API 不能处理特殊字符,因此不要尝试转换特殊字符。 你可以使用正则表达式对需要转换的字符串中的特殊字符进行过滤。 对需要转换的字符串进行一些处理,包括删除空格和对特殊字符串进行替换,删除等。 在一些特定的情况下,我们还是可以对特殊字符串进行处理的,这个时候你可以使用 NumberFormat 来先进行标记格式。 使用工具类,例如 NumberUtils.isNumber() 先对字符串进行检查。 总结 在这个页面中,我们对将 String 格式化为数字类型,使用 Java Number API 的方法和可能出现的异常进行了一些说明。 在这里我们看到了常见的导致异常的原因和我们可以避免的办法。   https://www.ossez.com/t/java-numberformatexception/13986

2022年06月06日 0Comments 27Browse 0Like Read more
Computer Science

Java 通过构造函数初始化 Integer 对象的方法将会被丢弃

通常,我们可以使用构造方法来创建一个整数对象,例如下面的代码: Integer aIntegerObj = new Integer("1"); 但是,上面的代码有可能在 IDE 中提示将会被丢弃。     将要被丢弃的原因是: Deprecated It is rarely appropriate to use this constructor. Use parseInt(String) to convert a string to a int primitive, or use valueOf(String) to convert a string to an Integer object. 简单来说这个使用这个构造方法创建整数对象的情况并不常见,所以 JDK 就打算丢弃掉这个构造方法创建整数对象的方法了。 可以使用 parseInt(String) 或者 valueOf(String) 来进行类型转换。 简单来说就是这个方法用到的情况并不多,并且不建议使用这个方法来创建新的数字类型对象了。 应该使用类型转换的方法来进行初始化。   https://www.ossez.com/t/java-integer/13987

2022年06月06日 0Comments 27Browse 0Like Read more
Computer Science

Discourse 支持中文用户名

Discourse 在默认安装的情况下是不支持中文用户名的输入的。 根据官方的说明,从 Discourse 2.3.0.beta9 版本开始,Discourse 就已经能够支持 Unicode 的用户名了,包括中文的用户名。 官方发布的文章为:https://meta.discourse.org/t/unicode-usernames-and-group-names/117737。 你需要对你的 Discourse 进行设置就行了。 设置位置 在管理员控制的设置中,搜索字符 unicode。 你就可以看到有个选项叫做 unicode usernames。 选择上这个选项就可以了。     如果你使用的是英文版语言的 Discourse 的话。 那么这个的配置选项就在这里了。     曾经在很久之前,有人讨论过这个内容,不过这个是在官方不支持的情况下。 目前你已经不需要安装这个插件了。   https://www.ossez.com/t/discourse/13983

2022年06月04日 0Comments 29Browse 0Like Read more
Computer Science

Git 如何从特定的提交中创建一个新的分支

有时候我们希望找到一个提交历史,然后从这个提交历史中创建一个分支。 很多人应该都会使用命令行工具来做,其实 IDEA 已经帮你做了。 IDEA 首先在 IDEA 中找到 Git,然后找到你的提交历史。 在找到提交历史后,可以选择鼠标的右键。 然后选择新分支。 你就可以从当前的提交历史中来创建一个新的分支了。 Source Tree 使用 SourceTree 也是一样的。 通过在提交历史中单击右键,然后选择分支,你就可在当前指定的提交历史中来创建一个新的分支了。 https://www.ossez.com/t/git/13981

2022年06月03日 0Comments 30Browse 0Like Read more
Computer Science

Maven 跳过测试的几种方式

在 Maven 对项目进行编译的时候,我们通常可能会希望跳过复杂的测试。     尤其是在开始项目还不是非常稳定的阶段。 命令行中使用 -Dmaven.test.skip=true 在命令行,只要简单的给任何目标添加 maven.test.skip 属性就能跳过测试: mvn install -Dmaven.test.skip=true 命令行中使用 -DskipTests 在 Maven 的命令中,使用参数 -DskipTests 来跳过测试 使用的命令为: mvn install -Dmaven.test.skip=true 修改 POM 文件 在pom.xml文件中增加配置 <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skip>true</skip> </configuration> </plugin> </plugins> </build> maven.test.skip 和 skipTests 的区别 -DskipTests,不执行测试用例,但编译测试用例类生成相应的class文件至target/test-classes下。 -Dmaven.test.skip=true,不执行测试用例,也不编译测试用例类。 简单来说,这 2 个参数的区别就是 -Dmaven.test.skip 这个参数跳过测试更加彻底,连测试类编译都不会编译。 如果不是非常糟糕的环境配置问题还是其他需求的话,测试类最好还是进行编译。因此使用 -DskipTests 参数。   https://www.ossez.com/t/maven/11034

2022年05月27日 0Comments 43Browse 0Like Read more
Computer Science

JDK 15 以上版本的字符串块

考察下下面的代码: public String textBlocks() { // THIS ONLY FOR JDK 15 return """ Get busy living or get busy dying. --Stephen King"""; } 我们可以看到上面的代码使用了 2 个引号 " 来表示一个字符串的块。 结论 上面的代码只能在 JDK 15 以上的版本才可以使用。 如果你使用的是 JDK 13 或者 14 的版本,你可以开启使用预览模式来让编译器通过。 因为我们的本地使用的是 JDK 11 编译器,上面的字符串表示方式在你的编译器上面会提示错误。   https://www.ossez.com/t/jdk-15/13979

2022年05月26日 0Comments 41Browse 0Like Read more
Computer Science

Java 8 中的设计模式策略

概述 在本篇文章中我们对可以在 Java 8 中的设计模式策略(strategy design pattern)进行一些简单的说明。 如果你对 Java 的设计模式不是非常清楚的话,可以先自行脑补下。 我们简单的总结就是将以前 Java 使用的接口和实现的设计模式,在 Java 8 中可以使用 lambda 函数来进行简化。 在下面内容中,我们首先提供了一个简单的设计模式样例,以及在传统的环境下我们是怎么实现这个设计模式的。     随后,我们将会使用 Java 8 中的 lambda 函数来进行实现,然后介绍一些有什么不同的地方。 模式策略 所谓的模式策略(strategy pattern)的定义就是能够让我们的程序在运行时(runtime)改变算法的表现。 在通常的情况下,我们会首先设计一个接口,然后在这个接口中定义我们需要使用的方法,然后使用不同的类来实现我们的接口定义的方法。 这种设计模式为我们在 Java 面向对象设计时候经常用到的。 让我们来考察下面的一个使用案例,针对不同的节日,我们针对某一个销售使用不同的定价策略,比如说圣诞节(Christmas),复活节(Easter)或者新年(New Year),我们使用的价格策略是不一样的。 首先我们需要在接口中定义一个 Discounter 方法,然后针对不同的节日来实现 Discounter 这个方法。 public interface Discounter { BigDecimal applyDiscount(BigDecimal amount); } 然后我们的目标是在复活节的时候打 5 折(50%),另外一个目标是在圣诞节的时候打 9 折(10%)。 随后我们就可以在下面的 2 个类中实现我们在接口中定义的方法。 public static class EasterDiscounter implements Discounter { @Override public BigDecimal applyDiscount(final BigDecimal amount) { return amount.multiply(BigDecimal.valueOf(0.5)); } } public static class ChristmasDiscounter implements Discounter { @Override public BigDecimal applyDiscount(final BigDecimal amount) { return amount.multiply(BigDecimal.valueOf(0.9)); } } 然后,我们在实现中使用这个策略: Discounter easterDiscounter = new EasterDiscounter(); BigDecimal discountedValue = easterDiscounter .applyDiscount(BigDecimal.valueOf(100)); assertThat(discountedValue) .isEqualByComparingTo(BigDecimal.valueOf(50)); 上面这个设计模式是我们在通常情况下使用的,但是比较头痛的是针对每一个方法,你需要在实现中都实现你需要的方法。 另外一个解决方案就是使用内部类型,但是这个内部类型并没有有太多的提高,你还是有不少的工作需要做。 例如下面使用内部类型的实现: Discounter easterDiscounter = new Discounter() { @Override public BigDecimal applyDiscount(final BigDecimal amount) { return amount.multiply(BigDecimal.valueOf(0.5)); } }; 使用 Java 8 如果你开始使用 Java 8 的话,我们知道 lambda 函数表达式可以做内部类型来使用,这样能够明显的降低多余的代码。 同时会让我们的代码看起来更加整洁和可读。 不管怎么样,使用 lambda 表达式提供了另外一种模式的实现,针对最开始的实现来说,Java 8 的实现提供了更多的一种选择。 降低代码的冗余 现在我们针对 EasterDiscounter 的实现,我们现在只是用 lambda 表达式来实现: Discounter easterDiscounter = amount -> amount.multiply(BigDecimal.valueOf(0.5)); 通过上面的代码,我们可以看到使用 lambda 表达式的实现看起来更加整洁,代码更加可读和便于维护,针对开始使用多行才能实现的内容,现在只需要使用一行就可以完成了。 更主要的是: ** 一个 lambda 表达式可以被用来替换匿名的内部类型**。 如果我们需要对多个折扣力度进行实现的话,使用 lambda 表达式就看起来更加漂亮了: List<Discounter> discounters = newArrayList( amount -> amount.multiply(BigDecimal.valueOf(0.9)), amount -> amount.multiply(BigDecimal.valueOf(0.8)), amount -> amount.multiply(BigDecimal.valueOf(0.5)) ); 如果我们需要对很多折扣力度进行定义的话,我们可以在 Java 8 中使用静态方法,然后这个定义将会在一个类中完成。 如果你愿意的话,Java 8 甚至可以让你在接口中定义静态方法。 对比在实体类和匿名内部类型之间进行选择,让我们在一个单独类中创建多个静态 lambda 表达式: public interface Discounter { BigDecimal applyDiscount(BigDecimal amount); static Discounter christmasDiscounter() { return amount -> amount.multiply(BigDecimal.valueOf(0.9)); } static Discounter newYearDiscounter() { return amount -> amount.multiply(BigDecimal.valueOf(0.8)); } static Discounter easterDiscounter() { return amount -> amount.multiply(BigDecimal.valueOf(0.5)); } } 通过上面的代码,我们可以看到使用了较少的代码,我们实现了很多的功能。 改进方法的创建 让我们来对 Discounter 接口再次进行修改,这次我们让 Discounter 接口继承 UnaryOperator 接口,然后添加一 combine() 方法: public interface Discounter extends UnaryOperator<BigDecimal> { default Discounter combine(Discounter after) { return value -> after.apply(this.apply(value)); } } 最开始的设计就是通过对 Discounter 接口的调整,能够让 Discounter 接口能够对折扣进行处理。 随着 UnaryOperator 接口被继承,我们可以使用 UnaryOperator 接口提供的 apply() 方法,我们只需要对 applyDiscount 进行替换就可以了。 combine() 方法为在 Discounter 接口中应用的一个抽象,使用一个内建的 apply() 函数来实现。…

2022年05月26日 0Comments 44Browse 0Like Read more
Computer Science

Java Optional 初始为空

如果你想对 Optional 进行初始化的话,你可能会考虑使用下面的代码: Optional<QualificationStateLabelInfo> stateSpecificLabel = null; 上面的代码编译和运行都没有问题。 如何初始化 正确的初始化代码是: Optional<QualificationStateLabelInfo> stateSpecificLabel = Optional.empty(); 上面将会把你定义的 Optional 初始化为空。     但是我们会避免使用 null。 https://www.ossez.com/t/java-optional/13975

2022年05月18日 0Comments 59Browse 0Like Read more
Computer Science

Java 8 开始新增的 Optional 类 - Optional 对象中的返回

使用 get() 来返回一个值 在对 Optional 对象完成一些检查和校验后,我们可以使用 get() 方法来返回对象中的值。 // returning Value With get() @Test public void givenOptional_whenGetsValue_thenCorrect() { Optional<String> opt = Optional.of("HoneyMoose"); String name = opt.get(); assertEquals("HoneyMoose", name); } 与 orElse() 或者 orElseGet() 方法不一样的地方是 get() 只会在 Optional 包装的对象不为 null 的时候返回值,否则这个方法将会抛出一个没有这个元素(no such element exception)的异常 。 @Test(expected = NoSuchElementException.class) public void givenOptionalWithNull_whenGetThrowsException_thenCorrect() { Optional<String> opt = Optional.ofNullable(null); String name = opt.get(); } 上面的方法显示了如何使用 get() 方法来获得 Optional 中元素的典型操作。 我们使用 Optional 的主要原因就是为了避免在程序中出现 Null 对象异常的这种情况,但是 get() 方法的这种操作还是会给你带来空对象异常的。 因此需要注意下这种代码编写方式,也有可能在 JDK 的后续版本中,这个 get() 方法有可能被取消掉,但是目前还不会。   正是因为这种情况,get() 这个方法也有可能出现空对象异常,在编码的时候还是需要注意下的。 使用 filter() 来进行条件返回 我们可以使用 filter() 方法在输出之前进行测试,然后过滤出满足我们条件的返回对象。 这个方法将会使用 Java 提供的谓语(predicate )作为参数来返回 Optional 对象。 如果通过了 Java 提供的谓语(predicate )测试的话,Optional 对象将会被原样返回。 如果,测试的 谓语(predicate )为 False 的话,那么一个空的 Optional 对象将会被返回。 @Test public void whenOptionalFilterWorks_thenCorrect() { Integer year = 2016; Optional<Integer> yearOptional = Optional.of(year); boolean is2016 = yearOptional.filter(y -> y == 2016).isPresent(); assertTrue(is2016); boolean is2017 = yearOptional.filter(y -> y == 2017).isPresent(); assertFalse(is2017); } filter() 方法通常用来处理你不需要的返回,或者处理满足你条件的返回。 例如在对用户电子邮件进行检查,或者用户密码进行检查的时候,我们可以设置这样一个 filter() 过滤器,当不满足我们设置条件的时候,我们让程序返回一个空的对象,以此来设置条件。 让我们看另外一个使用场景,我们希望购买一个调制解调器(modem),但是我们只关注的是价格,我们对信号灯并不敏感 我们希望对调制解调器在满足价格区间的时候获得一个通知: public class Modem { private Double price; public Modem(Double price) { this.price = price; } // standard getters and setters } 让我们让这个对象通过一些代码来检查这个对象是不是满足我们设定的价格区间. 下面的代码是我们不使用 Optional 的时候的代码。 从上面的代码来看,我们需要进行 Null 检查,然后获得价格,然后判断价格,更要命的更极端的情况价格也有可能为 null。 public boolean priceIsInRange1(Modem modem) { boolean isInRange = false; if (modem != null && modem.getPrice() != null && (modem.getPrice() >= 10 && modem.getPrice() <= 15)) { isInRange = true; } return isInRange; } 为了满足 Null 检查的所有条件,我们需要不停的 if 进行判断。我们需要通过这些 if 条件检查来确定是否满足我们的条件,并且这个代码看起来有点郁闷,但是实际上也确实就是这样写的。 @Test public void whenFiltersWithoutOptional_thenCorrect() { assertTrue(priceIsInRange1(new Modem(10.0))); assertFalse(priceIsInRange1(new Modem(9.9))); assertFalse(priceIsInRange1(new Modem(null))); assertFalse(priceIsInRange1(new Modem(15.5))); assertFalse(priceIsInRange1(null)); } 同时,你也有可能忘记某一个检查,比如说价格为 NULL 的时候怎么办。 这个检查在编译的时候是不会提示你的,只有程序真正上线运行了,出现了异常了,你才知道,我又忘记检查空了。 现在我们看看 Optional 中的 filter() 是怎么做的。 public boolean priceIsInRange2(Modem modem2) { return Optional.ofNullable(modem2).map(Modem::getPrice).filter(p -> p >= 10).filter(p -> p <= 15).isPresent(); } 你的程序精简到只需要一行就可以了。 map 这个方法只是简单的从对象中获得值,后面的过滤器才是对获得值进过滤的。 需要注意的是,使用 filter() 不会对输入的参数进行修改。 在我们的用例中,我们非常容易的就从我们的 Model 对象中获得了价格的属性。至于 map() 的使用我们在后面的内容中进行介绍。 针对上面的代码,首先如果对象出现 null 的时候是不会对你程序有任何影响的,还是能一直跑下去的。 其次就是逻辑非常简单,整个逻辑就是对价格进行判断,至于其他的 null 判断都是由 Optional 完成的。 @Test public void whenFiltersWithOptional_thenCorrect() { assertTrue(priceIsInRange2(new Modem(10.0))); assertFalse(priceIsInRange2(new Modem(9.9))); assertFalse(priceIsInRange2(new Modem(null))); assertFalse(priceIsInRange2(new Modem(15.5))); assertFalse(priceIsInRange2(null)); } 最开始的 If 代码也是可以完成价格的判断的,但是这个方法有着自身的缺陷,因此我们使用了…

2022年05月18日 0Comments 54Browse 0Like Read more
12345…167
Newest Hotspots Random
Newest Hotspots Random
网络编程常用的几种字符编码 Java 中的 String Pool 简介 有关 Java 9 的 String Java String 性能和优化 Java String 手工引用指针 Java String 文字(Literal)和 对象(Object)初始化
Jenkins 通过检查代码提交自动触发编译IntelliJ IDEA 2022 年版本中的作者提示Discourse 新用户可插入媒体的数量Discourse 的信任级别Java 使用 char[] Array 还是 String 存储字符串密码Java 字符串引用(String Interning)
Confluence 6 自定义登录界面 Python 生成 QR 二维码 Docker 文档编译 - 图片 Confluence 6 为 Active Directory 配置一个 SSL 连接预要求 Confluence 6 重新获得站点备份文件 新加坡,阿联酋航空这种小国家的航空公司为何能做大
Categories
  • Akka
  • Algorithm(算法)
  • AMQP
  • Angular
  • CI
  • Compile And CI
  • Computer Science
  • Confluence
  • DataBase
  • Gradle
  • H1B
  • Hibernate
  • IDE
  • Java
  • Jersey
  • Jira
  • MariaDB
  • PrestaShop
  • Spring
  • Spring Batch
  • U.S.
  • U.S. Travel
  • USRealEstate
  • 我的小厨

COPYRIGHT © 2020 HoneyMoose. ALL RIGHTS RESERVED.

THEME CWIKIUS.CN MADE BY VTROIS