如何避免Java踩坑教训,教你这三种

 

前言

学习Java很难。经验是最好的老师。经验教你克服错误。我从错误中吸取了教训。你可以从我的错误中吸取教训。 这是我通过艰苦的方式学到的东西,而您不必这样做。

1. Lambdas 可能会给你带来困难

Lambda通常超过 4 行代码。做的比应该做的多。更多的责任——你的工作记忆更难。更多行——多重责任 lambda。

您是否需要更改 lambda 中的变量? 你不能那样做。 为什么?如果 lambda 可以访问调用跨界变量,则可能会出现多线程问题。您不能从 lambda 内部更改调用变量。

lambda 中的快乐路径效果很好。运行时崩溃后,您会收到以下响应:

at [CLASS].lambda$null$2([CLASS].java:85) at [CLASS]$$Lambda$64/730559617.accept(Unknown Source)

Lambda 堆栈跟踪令人痛苦。名称被混淆、难以跟踪且难以调试。

调试 lambda 的更好方法是什么? 使用中间结果。

map(elem -> { int result = elem.getResult(); return result; });

更好的方法是使用高级 IntelliJ 调试技巧。使用TAB来选择要调试的代码。将此与中间结果相结合以获得更好的体验。

“当我们在包含 lambda 的行处停止时,如果我们按 F7(步入),那么 IntelliJ 将突出显示要调试的代码段。我们可以使用 Tab 切换要调试的块,一旦我们决定,然后我们再次单击 F7。”

如何从 lambda 访问调用跨界变量? 您只能访问 final 或有效的 final 变量。您需要包装调用变量。无论是AtomicType或您自己的类型。您可以从 lambda 更改包装的变量。

如何解决堆栈跟踪问题? 使用命名函数。您现在可以找到负责任的代码、审查逻辑并更快地解决问题。使用命名函数来减少神秘的堆栈跟踪。

相同的 lambda 重复? 把它放在一个命名函数中。您将有一个参考点。每个 lambda 都有一个生成的函数,这使得跟踪变得更加困难。

lambda$yourNamedFunction lambda$0

命名函数解决了另一个问题。命名函数会划分大lambdas,创建更小的代码块,并创建可插入的函数。

.map(this::namedFunc1).filter(this::namedFilter1).map(this::namedFunc2)

 

2. 你会遇到列表List问题

您需要使用 Lists。您需要 HashMaps 来获取类似字典的数据。您需要 TreeMap 角色。您不可能不使用集合。

你如何构建一个列表?你需要什么清单?你需要一个不可变或可变的列表吗?答案会影响代码的未来。早点选择正确的清单,否则就会受苦。

Arrays::asList创建“直写”列表。你不能用这个列表做什么?您无法更改已创建列表的大小。大小是不可变的。你可以做什么?设置元素、排序或其他不影响大小的操作。Arrays::asList小心使用,因为它的大小是不可变的,但内容不是。

new ArrayList()创建一个新的“可变”列表。

创建的列表支持哪些操作?这就是要谨慎的原因。

List::of 创建一个“不可变的”集合。大小是不变的,但是内容在某些条件下是不可变的,如果内容是原始值,即 int,则列表是不可变的。看下面的例子。

@Test public void testListOfBuilders() { System.out.println("### TESTING listOF with mutable content ###"); StringBuilder one = new StringBuilder(); one.append("a"); StringBuilder two = new StringBuilder(); two.append("a"); List<StringBuilder> asList = List.of(one, two); asList.get(0).append("123"); System.out.println(asList.get(0).toString()); } 输出: ### TESTING listOF with mutable content ### a123

您需要创建不可变对象并将它们放入List::of才能真正保证不可变, List::of不保证不变性。

3. 注释让你慢下来

你使用注解吗?你了解他们吗?你知道他们做什么吗? 自定义Logged注释 是否适用于每种方法?错误的。我已经使用 ourLogged来记录方法的参数。令我惊讶的是,它不起作用。您盲目地使用自定义注释。

@Transaction @Method("GET") @PathElement("time") @PathElement("date") @Autowired @Secure("ROLE_ADMIN") public void manage(@Qualifier('time')int time) { ... }

这段代码有什么不愉快的地方?有很多配置摘要。你会经常遇到这种情况。配置与常规代码混合在一起。本身还不错,但很难看。

注释是有代价的。读者为阅读付出的代价。我们为了更快的开发而交易冗长。

注释是为了减少样板代码。您不需要为每个端点编写日志逻辑。您不需要配置事务,使用@Transactional. 注释通过提取代码来减少样板。

好的,我们应该回到 XML 吗?不。我正在使用基于 Spring 的应用程序,并且使用 XML 进行配置是轻而易举的。我们确实有注释,但大部分配置都是在XML 中。模式指导配置,学习曲线并不陡峭。注释很方便。注释优势在于方便,XML 优势在于冗长。

这里没有明确的赢家,因为两者都在发挥作用。直到今天,我仍然使用 XML 和注释。当您发现重复的样板文件时,最好将注释背后的逻辑移动。例如,日志记录是一个很好的注释候选者。这个故事的寓意是:不要滥用注释,不要忘记 XML

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值