「解锁新姿势」 兄dei,你代码需要优化了
ztj100 2025-06-04 08:59 8 浏览 0 评论
前言
在我们平常开发过程中,由于项目时间紧张,代码可以用就好,往往会忽视代码的质量问题。甚至有些复制粘贴过来,不加以整理规范。往往导致项目后期难以维护,更别说后续接手项目的人。所以啊,我们要编写出优雅的代码,方便你我他,岂不美哉?
下面分享一些我在开发中常用的编码中小建议,如有不妥,欢迎大家一起交流学习。
卫语句
卫语句,就是把复杂的条件表达式拆分成多个条件表达式。比如 多个 if-elseif-else 嵌套, 可以拆分成多个 if。如下面代码
代码:
-------------------- before --------------------
public void today() {
if (isWeekend()) {
if (isFee()) {
System.out.println("study Android");
} else {
System.out.println("play a game");
}
} else {
System.out.println("go to work");
}
}
-------------------- after (建议) --------------------
public void today() {
// 提前过滤掉`特殊情况`
if (!isWeekend()) {
System.out.println("go to work");
return; // 提前return
}
//提前过滤掉`特殊情况`
if (isFee()) {
System.out.println("study Android");
return; // 提前return
}
// 更关注于 `核心业务`代码实现。
System.out.println("play a game");
}
小函数
我们平常开发的时候,应该编写小而美函数,避免函数过长。一般函数最好在15行以内(建议) 我们看看下面代码:
-------------------- before --------------------
if (age > 0 && age < 18){
System.out.println("小孩子");
}
if (number.length() == 11){
System.out.println("符合手机号");
}
-------------------- after (建议) --------------------
private static boolean isChild(int age) {
return age > 0 && age < 18;
}
private static boolean isPhoneNumber(String number) {
return number.length() == 11;
}
if (isChild(age)){
System.out.println("小孩子");
}
if (isPhoneNumber(number)){
System.out.println("符合手机号");
}
把判断语句抽取成一个个小函数, 这样代码更加清晰明了。
迪米特法则
概念:
迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简写LKP),就是说一个对象应当对其他对象有尽可能少的了解。例如 当一条语句中 一个对象出现两个 . (student.getName().equals("张三")) 就是代码坏味道的表现,如下代码所示。
代码:
-------------------- before --------------------
public class Student {
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static void main(String[] args) {
Student student = new Student("张三");
// 注意看这里,
// 这里获取 student的name属性,在根据name属性进行判断
if (StringUtils.isNotBlank(student.getName()) && student.getName().equals("张三")) {
System.out.println("我的好朋友是 " + student.getName());
}
}
-------------------- after (建议) --------------------
public class Student {
... 省略name代码
// 新增一个 判断是否是我的好朋友方法
public boolean isGoodFriend(){
return StringUtils.isNotBlank(this.name) && this.name.equals("张三");
}
}
public static void main(String[] args) {
Student student = new Student("张三");
// 根据迪米特法则,把判断逻辑,抽取到 Student 内部,暴露出方法(isGoodFriend)
if (student.isGoodFriend()){
System.out.println("我的好朋友是 " + student.getName());
}
}
IDEA/Android Studio 抽取方法快捷键: option + command + M
Map 提取对象
我们在平常开发中,会使用到map,但是在面向对象开发理念中,一个 map的使用,往往就会错过了 Java Bean。建议使用 Java Bean 更直观。如下代码:
public static void main(String[] args) {
-------------------- before --------------------
Map<String, String> studentMap = new HashMap<>();
studentMap.put("张三", "男");
studentMap.put("小红", "女");
studentMap.put("李四", "男");
studentMap.forEach((name, sex) -> {
System.out.println(name + " : " + sex);
});
-------------------- after (建议) --------------------
List<Student> students = new ArrayList<>();
students.add(new Student("张三", "男"));
students.add(new Student("小红", "女"));
students.add(new Student("李四", "男"));
for (Student student : students) {
System.out.println(student.getName() + ":" + student.getSex());
}
}
笔者在编写这点时候,有所顾虑。肯定有小伙伴跳出来说,map 和 bean 不是一样吗?用map 我还可以省去思考如何命名Class呢。但是从代码规范来说,这样代码设计不是更符合 Java 面向对象的思想吗?
Stream
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。使得代码调用起来更加优雅~ 直接来看代码:
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student("张三", "男"));
students.add(new Student("李四", "男"));
students.add(new Student("小红", "女"));
students.add(new Student("小花", "女"));
students.add(new Student("小红", "女"));
-------------------- before --------------------
//统计男生个数
//传统的 for each 循环遍历
long boyCount = 0;
for (Student student : students) {
if (student.isBoy()) {
boyCount++;
}
}
System.out.println("男生个数 = " + boyCount);
-------------------- after (建议) --------------------
//统计男生个数
//stream 流遍历
long count = students.stream()
.filter(Student::isBoy) // 等同于.filter(student -> student.isBoy())
.count();
System.out.println("男生个数 = " + boyCount);
}
相比与 传统的 For 循环,更推荐大家使用 stream 遍历。 stream 流的链式调用,还有许多骚操作,如 sorted, map, collect等操作符,可以省去不必要if-else,count等判断逻辑。
多态
Java 三大特性之一,多态,相信大家都不会陌生,多态的好处就是根据对象不同类型采取不同的的行为。我们常常在编写 switch 语句的时候,如果改用多态,可以把每个分支,抽取到一个子类内的覆写函数中,这就更加灵活。
我们有这样一个需求,编写一个简单计算器方法,我们先来看一小段代码:
-------------------- before --------------------
public static int getResult(int numberA, int numberB, String operate) {
int result = 0;
switch (operate) {
case "+":
result = numberA + numberB;
break;
case "-":
result = numberA - numberB;
break;
case "*":
result = numberA * numberB;
break;
case "/":
result = numberA / numberB;
break;
}
return result;
}
-------------------- after (建议) --------------------
abstract class Operate {
abstract int compute(int numberA, int numberB);
}
class AddOperate extends Operate {
@Override
int compute(int numberA, int numberB) {
// TODO 在这里处理相关逻辑
return numberA + numberB;
}
}
... SubOperate, MulOperate, DivOperate 也和 AddOperate一样这里就不一一贴出
public static int getResult(int numberA, int numberB, String operate) {
int result = 0;
switch (operate) {
case "+":
result = new AddOperate().compute(numberA, numberB);
break;
case "-":
result = new SubOperate().compute(numberA, numberB);
break;
case "*":
result = new MulOperate().compute(numberA, numberB);
break;
case "/":
result = new DivOperate().compute(numberA, numberB);
break;
}
return result;
}
有小伙伴可能会说,你这不是更复杂了吗?
对比起单纯的switch,我们可以这样理解:
但是这里会存在一些问题,如果我们新增一个平方根,平方等计算方式, 就需要修改 switch 里面的逻辑,新增一个条件分支。下面我们再来看看更进一步的优化。
反射
通过上面例子,我们可以进一步优化,通过反射生成对应的 Class,然后在调用compute方法。如下代码:
public static <T extends Operate> int getResult(int numberA, int numberB, Class<T> clz) {
int result = 0;
try {
return clz.newInstance().compute(numberA, numberB);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
return result;
}
}
public static void main(String[] args) {
// 调用的时候直接传递 class 即可
System.out.println(getResult(1, 2, SumOpearte.class));
}
根据传入 class 参数,然后生成对应 Opearte处理类, 对比多态方式,我们这里采用反射,使得代码耦合度大大降低,如果在增加平方根,平方等计算方式。我们只需要 新增一个 class 继承 Opearte 即可,getResult 不用做任何修改。
需要注意的是,不是所有switch语句都需要这样替换, 在面对简单的 switch语句,就不必要了, 避免过度设计的嫌疑。如下代码:
public String getResult(int typeCode) {
String type = "";
switch (typeCode) {
case 0:
type = "加法";
break;
case 1:
type = "减法";
break;
case 2:
type = "乘法";
break;
case 3:
type = "除法";
break;
}
return type;
}
最后
以上就是我在编码上的一些小建议,如有不妥,欢迎大家一起交流学习。
零基础学习Java编程,可以加个关注,需要Java基础学习资料总结,可以私信我,发送“编程”可以收到入口。
原链接:
https://juejin.cn/post/6844903983744548877
相关推荐
- 拒绝躺平,如何使用AOP的环绕通知实现分布式锁
-
如何在分布式环境下,像用synchronized关键字那样使用分布式锁。比如开发一个注解,叫@DistributionLock,作用于一个方法函数上,每次调方法前加锁,调完之后自动释放锁。可以利用Sp...
- 「解锁新姿势」 兄dei,你代码需要优化了
-
前言在我们平常开发过程中,由于项目时间紧张,代码可以用就好,往往会忽视代码的质量问题。甚至有些复制粘贴过来,不加以整理规范。往往导致项目后期难以维护,更别说后续接手项目的人。所以啊,我们要编写出优雅的...
- 消息队列核心面试点讲解(消息队列面试题)
-
Rocketmq消息不丢失一、前言RocketMQ可以理解成一个特殊的存储系统,这个存储系统特殊之处数据是一般只会被使用一次,这种情况下,如何保证这个被消费一次的消息不丢失是非常重要的。本文将分析Ro...
- 秒杀系统—4.第二版升级优化的技术文档二
-
大纲7.秒杀系统的秒杀活动服务实现...
- SpringBoot JPA动态查询与Specification详解:从基础到高级实战
-
一、JPA动态查询概述1.1什么是动态查询动态查询是指根据运行时条件构建的查询,与静态查询(如@Query注解或命名查询)相对。在业务系统中,80%的查询需求都是动态的,例如电商系统中的商品筛选、订...
- Java常用工具类技术文档(java常用工具类技术文档有哪些)
-
一、概述Java工具类(UtilityClasses)是封装了通用功能的静态方法集合,能够简化代码、提高开发效率。本文整理Java原生及常用第三方库(如ApacheCommons、GoogleG...
- Guava 之Joiner 拼接字符串和Map(字符串拼接join的用法)
-
Guave是一个强大的的工具集合,今天给大家介绍一下,常用的拼接字符串的方法,当然JDK也有方便的拼接字符串的方式,本文主要介绍guava的,可以对比使用基本的拼接的话可以如下操作...
- SpringBoot怎么整合Redis,监听Key过期事件?
-
一、修改Redis配置文件1、在Redis的安装目录2、找到redis.windows.conf文件,搜索“notify-keyspace-events”...
- 如何使用Python将多个excel文件数据快速汇总?
-
在数据分析和处理的过程中,Excel文件是我们经常会遇到的数据格式之一。本文将通过一个具体的示例,展示如何使用Python和Pandas库来读取、合并和处理多个Excel文件的数据,并最终生成一个包含...
- 利用Pandas高效处理百万级数据集,速度提升10倍的秘密武器
-
处理大规模数据集,尤其是百万级别的数据量,对效率的要求非常高。使用Pandas时,可以通过一些策略和技巧显著提高数据处理的速度。以下是一些关键的方法,帮助你使用Pandas高效地处理大型数据集,从而实...
- Python进阶-Day 25: 数据分析基础
-
目标:掌握Pandas和NumPy的基本操作,学习如何分析CSV数据集并生成报告。课程内容...
- Pandas 入门教程 - 第五课: 高级数据操作
-
在前几节课中,我们学习了如何使用Pandas进行数据操作和可视化。在这一课中,我们将进一步探索一些高级的数据操作技巧,包括数据透视、分组聚合、时间序列处理以及高级索引和切片。高级索引和切片...
- 原来这才是Pandas!(原来这才是薯片真正的吃法)
-
听到一些人说,Pandas语法太乱、太杂了,根本记不住。...
- python(pandas + numpy)数据分析的基础
-
数据NaN值排查,统计,排序...
- 利用Python进行数据分组/数据透视表
-
1.数据分组源数据表如下所示:1.1分组键是列名分组键是列名时直接将某一列或多列的列名传给groupby()方法,groupby()方法就会按照这一列或多列进行分组。按照一列进行分组...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)
- vmware17pro最新密钥 (34)
- mysql单表最大数据量 (35)