1. 类设计原则

solid 类设计原则:

单一职责原则(SRP):一个类应该只负责一件事。
开闭原则(OCP):软件组件应该对扩展开发,对修改关闭。
里氏替换原则(LSP):子类必须能够完全替换基类。
接口隔离原则(ISP):客户端不应该依赖他不需要的接口。
依赖导致原则(DIP):依赖抽象,而不是细节。

image.png

2. 静态类处理异常

  1. public class TestExceptions {
  2. public static void main(String[] args)
  3. {
  4. try
  5. {
  6. throw new DBExeption.NoData("No row found for id : x");
  7. }
  8. catch(Exception e)
  9. {
  10. e.printStackTrace();
  11. }
  12. }
  13. }

优点:

  1. 即便开发者写了难以读懂的错误信息,也可以弄懂具体错误。
  2. 支持不同异常实例处理不同的异常场景。
  3. 不需要使用单个异常覆盖许多异常的情况。
  4. 日志更具有意义和可读性。

3. Java 异常

java中的异常层次结构

image.png

  1. 不要吞下异常,要做处理。
  2. 抛出已检查的异常
  3. 不要捕获 Exception 类而是捕获特定的子类
  4. 永远不要抓住 Throwable 类
  5. 始终正确地将异常包装在自定义异常中,以便不会丢失堆栈跟踪
  6. 记录异常或抛出它但从不同时执行
  7. 永远不要从 finally 块中抛出任何异常
  8. 始终只捕获您可以实际处理的异常
  9. 不要使用 printStackTrace()语句或类似方法
  10. 如果您不打算处理异常,请使用 finally 块而不是 catch 块
  11. 记住“提早赶快”的原则
  12. 处理异常后始终清理
  13. 仅从方法中抛出相关的异常
  14. 切勿在程序中使用流控制异常
  15. 验证用户输入以在请求处理的早期捕获不利条件
  16. 使用模板方法重复 try-catch

4. Spring 配置文件最佳实践

1)为每个配置文件添加标题注释
2)使用一致的命名约定
3)架构引用中没有版本号
4)优先选择构造函数注入的 setter 注入
5)首选构造函数参数匹配的索引类型
6)在扩展表单上使用快捷方式表单
7)尽可能重用 bean 定义
8)始终使用 id 作为 bean 标识符
9)尽量避免自动装配
10)始终使用类路径前缀
11)始终外部化属性
12)在开发阶段使用依赖性检查
13)不要滥用/过度使用依赖注入

5. Java 包装类内部缓存

整数缓存

  1. public class IntegerCacheDemo {
  2. public static void main(String[] args) {
  3. Integer a1 = 100;
  4. Integer a2 = 100;
  5. Integer a3 = new Integer(100);
  6. System.out.println(a1 == a2);
  7. System.out.println(a1 == a3);
  8. }
  9. }
  10. Output:
  11. true
  12. false

第一个print语句将打印为true; 表示两个变量都指向同一个实例。但是,第二个print语句打印为false,因为新的Integer(..)在单独的内存位置创建了一个新的实例。因此,如果要使用此缓存,请始终使用原始赋值来引用变量或使用valueOf()方法。

修改缓存大小

如果要存储更多实例,可以使用运行时参数,如下所示:
-Djava.lang.Integer.IntegerCache.high = 2000
上面的语句将使缓存存储从-127到1000的实例。请记住,截至目前,没有像-Djava.lang.Integer.IntegerCache.low这样的属性。可能在将来,也可能会添加。

其他包装类

在上面的讨论中,我已经讨论过Integer类中的缓存,但是如果事实上所有的包装类都提供了这种功能。以免见到它们:

  1. java.lang.Boolean将两个内置实例存储为TRUE和FALSE,如果未使用new关键字,则返回它们的引用。
  2. java.lang.Character有一个缓存,用于unicodes 0和127之间的字符(ascii-7 / us-ascii)。
  3. java.lang.Long的缓存长度介于-128到+127之间。
  4. java.lang.String有一个全新的字符串池概念。

6. ToString 最佳实践

  • Java 使用 ToStringBuilder 覆盖 toString()

7. Java 8 Streams

另一个重大变化是Java 8 Streams API,它提供了一种以各种方式处理一组数据的机制,包括过滤,转换或任何其他可能对应用程序有用的方式。

Java 8中的Streams API支持不同类型的迭代,您只需定义要处理的项集,要对每个项执行的操作以及要存储这些操作的输出。

流API的示例。在此示例中,items 是 String 值的集合,您希望删除以某些前缀文本开头的条目。

List items;
String prefix;
List filteredList = items.stream().filter(e -> (!e.startsWith(prefix))).collect(Collectors.toList());

items.stream()表示我们希望 items使用Streams API处理集合中的数据。

8. Java 8日期/时间API更改

新的日期和时间API /类(JSR-310),也称为ThreeTen,它们只是改变了您在Java应用程序中处理日期的方式。

日期

Date阶级甚至已经过时了。用于替换Date类的新类是LocalDateLocalTimeLocalDateTime

  1. LocalDate类代表一个日期。没有时间或时区的表示。
  2. 这个LocalTime班代表一个时间。没有日期或时区的表示。
  3. LocalDateTime类代表一个日期-时间。没有时区的表示。

如果您希望使用区域信息的日期功能,那么拉姆达为您提供额外的3类类似于一个,即上面OffsetDateOffsetTimeOffsetDateTime。时区偏移可以用“+05:30”或“欧洲/巴黎”格式表示。这是通过使用另一个类来完成的ZoneId

  1. LocalDate localDate = LocalDate.now();
  2. LocalTime localTime = LocalTime.of(12, 20);
  3. LocalDateTime localDateTime = LocalDateTime.now();
  4. OffsetDateTime offsetDateTime = OffsetDateTime.now();
  5. ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Paris"));

时间戳和持续时间

为了在任何时刻表示特定的时间戳,需要使用的是类Instant。本Instant类表示时间纳秒的精度瞬间。Instant上的操作包括与另一个操作的比较Instant以及添加或减去持续时间。

  1. Instant instant = Instant.now();
  2. Instant instant1 = instant.plus(Duration.ofMillis(5000));
  3. Instant instant2 = instant.minus(Duration.ofMillis(5000));
  4. Instant instant3 = instant.minusSeconds(10);

Durationclass是java语言中第一次带来的全新概念。它表示两个时间戳之间的时差。

  1. Duration duration = Duration.ofMillis(5000);
  2. duration = Duration.ofSeconds(60);
  3. duration = Duration.ofMinutes(10);

Duration处理小的时间单位,如毫秒,秒,分钟和小时。它们更适合与应用程序代码交互。要与人交互,你需要获得更大的持续时间,这些持续时间Period课程一起呈现。

  1. Period period = Period.ofDays(6);
  2. period = Period.ofMonths(6);
  3. period = Period.between(LocalDate.now(), LocalDate.now().plusDays(60));