Java开发之上班摸鱼!写最少的代码!

I 前言


本次分享一下我所知道的如何写最少的代码的小技巧,如果你有更好的方案,欢迎在评论区留言,方案很棒的话,加我交流圈,为你送上冬天的一杯奶茶~

在这里插入图片描述

Java:我想返回多个返回值


秀一下Go的多返回值:

package main
import "fmt"// 返回 X + Y 和 X * Y
func Computer(X, Y int) (int, int) {return X + Y, X * Y
}

众所周知,Java仅支持单一返回值,一般情况下如果需要返回多个对象,我们会根据代码语义选择容器或者新建一个新的类,把我们需要的数据包起来。
这样做有没有问题?当然没有问题,但是瑕疵就在于:可能会产生没啥语义但又不得不存在的中间类,我个人非常讨论该类代码,那么该如何解决这种问题呢?
首先需要认识到,解决方案必须满足几个要求:

  • 代码可复用
  • 语义要清晰
  • 安全

既然如此,我们可以采用泛型来满足复用、语义清晰的要求,用中间类来满足代码安全性的要求,代码如下:

public class MultipleTwoReturn<A, B> {/** 第一个返回值 **/private final A first;/** 第二个返回值 **/private final B second;public MultipleTwoReturn(A first, B second) {this.first = first;this.second = second;}// 省略Get方法
}

同时,我们可以依赖于继承,让该工具类拓展更多的参数:

public class MultipleThreeReturn<A, B, C> extends MultipleTwoReturn<A, B> {/** 第三个返回值 **/private final C third;public MultipleThreeReturn(A first, B second, C third) {super(first, second);this.third = third;}
}

测试类:

public class MultipleApp {public static void main(String[] args) {MultipleTwoReturn<Integer, String> returnTest = MultipleApp.getReturnTest();System.out.println(returnTest.getFirst());System.out.println(returnTest.getSecond());}private static MultipleTwoReturn<Integer, String> getReturnTest() {MultipleTwoReturn<Integer, String> demo = new MultipleTwoReturn<>(0, "Kerwin Demo.");return demo;//加入Java开发交流君样:756584822一起吹水聊天}
}

本质还是普通对象,但是加上泛型后威力剧增!由于在方法定义时就强制了泛型约束,语义非常清晰,同时可以完全杜绝上述的无语义中间类,当然一些必要的,有业务含义的组装类,不建议使用这种方式。

泛型:我想new一个对象

想利用作为泛型约束,却需要new一个T,但是Java它new不出来啊 😂

之前写过一个通用的Java爬虫接口,里面有一个功能就是传入目标网页的即可获取到针对不同网页设计的Bean,大概如下所示:

public interface SpiderBeansHandle<T> {/** 获取Url **/String getUrl();/** 获取Cookie **/String getCookie();/** 获取CSS selector **/String getSelector();// ....}

中间关键的一点即如何获取到这个Bean,那个时候我只有一个想法:new 一个 T

事实证明,我过于天真了 🙄

但是换种思路,既然new不出来,那我就返回一下吧,于是代码出炉了~

public interface SpiderBeansHandle<T> {/*** 获取Url*/String getUrl();/*** 获取Cookie*/String getCookie();/**** 获取CSS selector*/String getSelector();/**** 解析Element* @param element  element*/T parseElement(Element element);/**** Get Beans* @param handle  Bean对象 | handle对象* @param <T>     Bean类型* @return        List<Beans>*/static <T> List<T> getBeans(SpiderBeansHandle<T> handle) {List<T> list = new ArrayList<>();List<Element> elements = SpiderUtils.getElementWithCookie(handle.getUrl(), handle.getSelector(), handle.getCookie());for (Element element : elements) {T bean = handle.parseElement(element);if (bean != null) {list.add(bean);}//加入Java开发交流君样:756584822一起吹水聊天}return list;}
}

关键一步就在于:

/**** 解析Element* @param element  element*/
T parseElement(Element element);

那么这个小技巧有什么用呢?仔细看会不会觉得它像一种设计模式的变形体?没错!真相只有一个:模板方法模式
我需要一个处理爬虫的通用接口,因为简单爬虫无非就是拿到url然后请求,解析细节封装到自身的Bean里,然后获取一个列表,那么在开发业务代码的时候类似,肯定有某些场景和需求具有高度的一致性,那么使用这种设计方案即可大大的减少重复代码~


方法:你到底想干嘛?


咱们在写代码的时候有没有遇到过这种问题?写了一个工具类方法,但是功能又过于单一,虽说单一原则好吧,但是一个小逻辑写一堆方法,总感觉不得劲,如何解决咧?
Java8提供的函数式编程即可帮我们一定程度上解决这种问题,如:

// 写一个获取文件列表,且判断是否为txt结尾的工具类方法,新手会这么写
public static File getFileWithTxt(String path) throws IOException {File file = new File(path);if (!file.exists()) {throw new IOException("File is not exist.");}if (file.getName().endsWith(".txt")) {return file;}return null;
}//加入Java开发交流君样:756584822一起吹水聊天

老手一般会把 .txt 作为参数传入,但是某一天我需要判断文件大小,文件长度,甚至是文件内容的时候,我该咋办?再写N个?

最好的方案即传入 Predicate 谓词,让调用者自定义处理逻辑,然后再把最常用的逻辑基于该方法复写一下,拓展性Max!代码如下:

/**** 文件夹谓词匹配* @param file          文件* @param predicate     谓词匹配* @return              List<File>* @throws IOException  IOException*/
public static List<File> listFilesInDirWithFilter(File file, Predicate<String> predicate) throws IOException {if (!file.exists()) {throw new IOException("File is not exist.");}List<File> fileList = new ArrayList<>();if (file.isDirectory()) {File[] files = file.listFiles();for (File f : Objects.requireNonNull(files)) {fileList.addAll(listFilesInDirWithFilter(f, predicate));}} else {if (predicate.test(file.getName())) {fileList.add(file);}}return fileList;
}

类似的还比如说处理 IO,直接上代码:

public static void readLine(BufferedReader br, Consumer<String> handle, boolean close) {String s;try {while (((s = br.readLine()) != null)) {handle.accept(s);}} catch (IOException e) {e.printStackTrace();} finally {if (close && br != null) {try {br.close();} catch (IOException e) {e.printStackTrace();}}}
}//加入Java开发交流君样:756584822一起吹水聊天

方法说你到底想干嘛?!算了,你想干嘛就干嘛吧,请随意😎~

重载:写的更多也是为了写的更少


写的更多也是为了写的更少,这句话乍一听感觉非常矛盾,但是编程经验比较丰富的小伙伴应该能体会到方法重载的威力,尤其是在写工具类或者底层接口的时候,建议大家先写一个大而全的内部方法,然后一点点去根据需要重载它,会有意想不到的好处。
最简单的例子,如下:

// Root 方法//加入Java开发交流君样:756584822一起吹水聊天
private static void readLine(BufferedReader br, Consumer<String> handle, boolean close) {String s;try {while (((s = br.readLine()) != null)) {handle.accept(s);}} catch (IOException e) {e.printStackTrace();} finally {if (close && br != null) {try {br.close();} catch (IOException e) {e.printStackTrace();}}}
}
// 重载方法一
public static void readLine(String path, Consumer<String> handle, boolean close) {try {BufferedReader br = new BufferedReader(new FileReader(path));readLine(br, handle, close);} catch (FileNotFoundException e) {e.printStackTrace();}
}// 重载方法二
public static void readLine(String path, Consumer<String> handle) {readLine(path, handle, true);
}//加入Java开发交流君样:756584822一起吹水聊天

重载可以让我们的方法调用方式变得丰富多彩,在语义明确的情况下,写代码有如神助,配合函数式编程,可以让工具类或者底层接口的能力大大增强。
同时,当我们需要调整某一个方法逻辑时,也可以使用继续重载的方式,将影响面降到最小,尽量不动其他模块的代码。

终极:从设计模式到抽象


与其说是如何写最少的代码,不如说是:如何只写真正有价值的代码。

通过良好的设计模式或者其变形体,我们可以得到高内聚低耦合的代码,这是一个非常好的思路。

另一个思路,所有人都认同一点:程序 = 算法 + 数据结构,选择好正确的数据结构可以事倍功半,比如说我们做类似文件夹需求的时候,会想到使用链表或者树结构,在做如:如何高效的给用户发送生日短信时会想到用堆结构(用当前时间对比堆中的最大值,满足则继续迭代,减少遍历)等等。
这其实都是抽象,或深或浅而已,我最开始学习Java的时候,老师会说一句话:万物皆为对象,我们来看看上面的技巧各自对应着什么?

  • 多返回值:封装对象 + 泛型约束
  • 泛型:封装对象的公共接口,高度抽象
  • 函数式方法:把方法当作一个对象
  • 重载:对象方法(行为)的不断演化

所以如何只写真正有价值的代码?官方一点的话就是:把变化的抽象出来,那么到底该怎么抽?

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

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

相关文章

Windows 11 预览版 Build 22000.120 发布

微软现已发布第五个 Windows 11 预览版更新 KB5005188&#xff0c;版本号升级至 Build 22000.120。本次更新面向 Dev 频道和 Beta 频道的 Windows 预览体验成员推出。Windows 11 Insider Preview Build 22000.120 主要变化如下&#xff1a;1.全新的 Family Safety&#xff08;家…

robocopy帮助

一 Robocopy简介 Robocopy 是一个功能超强的32位的文件复制工具&#xff0c;该工具来自windows资源包&#xff0c;可以直接在网上下载。 使用Robocopy你能够拷贝单个目录&#xff0c;或迭代的拷贝目录及其所有的子目录。该工具通过文件是否存在于源目录&#xff0c;目标目录&am…

有趣的灵魂连墓碑都很酷! | 今日趣图

全世界只有3.14 % 的人关注了青少年数学之旅&#xff08;图源别是个沙雕吧&#xff0c;侵权删&#xff09;

实施Exchange 2013中的 MailTip

实施Exchange 2013中的 MailTip邮件提示是用户撰写邮件时向其显示的提示性消息。Microsoft Exchange Server 2013 将分析邮件&#xff08;包括向其发送了邮件的收件人的列表&#xff09;&#xff0c;如果检测到潜在问题&#xff0c;它将使用邮件提示在邮件发送之前通知用户。借…

防弹玻璃为啥会被钢球砸碎?这就是一道高中物理题!

全世界只有3.14 % 的人关注了青少年数学之旅马斯克&#xff0c;硅谷钢铁侠&#xff0c;全世界最具煽动力的企业家。旗下公司特斯拉最新电动皮卡&#xff0c;一经亮相就欢呼一片&#xff0c;传播到炸&#xff0c;看起来又要重新定义一个品类。然而也有网友“提醒”——如今的马斯…

八种ADSL接入情况中断流现象分析

转载自&#xff1a;网盟技术[url]http://technic.txwm.com[/url] 线路不稳定 如果住所离电信局太远(5公里以上)可以向电信部门申报。确保线路连接正确(不同的话音分离器的连接方法有所不同&#xff0c;请务必按照说明书指引正确连接)。同时确保线路通讯质量良好没有被干扰&…

Java之jdk与jre的区别

很多程序员已经干了一段时间java了依然不明白jdk与jre的区别。 JDK就是Java Development Kit.简单的说JDK是面向开发人员使用的SDK&#xff0c;它提供了Java的开发环境和运行环境。SDK是Software Development Kit 一般指软件开发包&#xff0c;可以包括函数库、编译程序等。 …

设计模式之组合

组合模式介绍一棵树结构组合模式是把相似对象或方法组合成一组可被调用的结构树对象的设计思路。组合模式不只是可以运用于规则决策树&#xff0c;还可以做服务包装将不同的接口进行组合配置&#xff0c;对外提供服务能力&#xff0c;减少开发成本。组合模式的主要解决的是一系…

leetcode中的状态机类型的题目

1 总结 一般是涉及到多个状态之间的转换&#xff0c;需要定义一个具有多个枚举值的变量&#xff0c;各个状态之间通过各种条件互相变化 2 LC57. 插入区间 2.1 解析 先是要确定新区间插入到哪一个位置&#xff08;也有可能&#xff09;&#xff0c;插入后需要确定这个区间是否…

如何用Python进行数据探索,探索竞赛优胜方案?

全世界只有3.14 % 的人关注了 青少年数学之旅 AI这个词相信大家都非常熟悉&#xff0c;近几年来人工智能圈子格外热闹&#xff0c;光是AlphoGo就让大家对它刮目相看。 随着大数据时代信息科技的快速发展&#xff0c;各种各样的数据充斥着我们的生活。而我们又当如何有效利用数据…

联想ThinkPad笔记本广告向苹果MacBook Air开战

联想ThinkPad笔记本广告向苹果MacBook Air开战 [url]http://www.sina.com.cn[/url] 2008年03月24日 07:21 新浪科技联想ThinkPad X300笔记本广告&#xff0c;暗讽苹果MacBook AirMacbook Air最厚的地方仅有1.94cm&#xff0c;边缘仅0.4cm视频&#xff1a;ThinkPad X300对比Mac…

基于 gRPC 和 .NET Core 的服务器流

原文&#xff1a;https://bit.ly/3lpz8Ll作者&#xff1a;Chandan Rauniyar翻译&#xff1a;精致码农-王亮早在 2019 年&#xff0c;我写过《用 Mapbox 绘制位置数据》一文&#xff0c;详细介绍了我如何通过简单的文件上传&#xff0c;用 Mapbox 绘制约 230 万个位置点。本文介…

jQuery入门[2]-选择器[转]

jQuery之所以令人爱不释手&#xff0c;在于其强大的选择器表达式令DOM操作优雅而艺术。jQuery的选择符支持id,tagName,css1-3 expressions,XPath&#xff0c;参见&#xff1a;http://docs.jquery.com/SelectorsDEMO:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Tran…

是个狠角色。。 | 今日最佳

全世界只有3.14 % 的人关注了青少年数学之旅&#xff08;图源洱海弥&#xff0c;侵权删&#xff09;

构建Windows Server 2008虚拟实验室

在阅读新闻稿时&#xff0c;有很多文章和指导&#xff0c;都有一些帮助&#xff0c;但却没有针对Windows Server 2008的手把手经验可供参考。对管理员来说&#xff0c;要熟悉这个服务器系统的最好方法是确定它的特性是如何给他们的Windows环境带来便利。 先前我描述了如何方便地…

eclipse配置tomcat 和JRE环境

配置JRE环境&#xff0c;通俗点讲就是添加一个不同版本的jdk window——preferences——java——installed jres 点击add添加 选择standard VM 择一个本机正确的jdk路径 name和下面lib加载都是系统自动完成的 选择好路径后 点 finish就ok了 配置tomcat window——preferen…

为什么我的 Func 如此之慢?

咨询区 Ricky G&#xff1a;我正在给项目做性能和代码优化&#xff0c;比如将重复的代码提炼成到一个可重用的方法中&#xff0c;为了能够达到可重用目的&#xff0c;我用 Func<T> 作为方法参数。public int Calculate(Func<int> expr){return expr();}当我用 Benc…

[转载MSDN]IIS 7.0中的Live Smooth Streaming -入门

IIS Live Smooth Streaming - 测试版是Internet 信使服务 (IIS) 7.0的一个扩展&#xff0c;它能提供流畅的视频流媒体&#xff0c;并且可以根据客户端的网络带宽和CPU的执行能力的改变&#xff0c;随时的调整视频质量。 IIS Live Smooth Streaming允许Microsoft Silverlight客户…

为啥饮料瓶大都是圆的,牛奶盒却是方的?

全世界只有3.14 % 的人关注了青少年数学之旅一提起喝饮料和牛奶你们是不是就来精神了但是喝了这么久的饮料你有没有想过一个问题为什么饮料瓶一般都是圆的&#xff1f;而牛奶盒却是方的&#xff1f;有的人可能会说饮料瓶要拿在手上当然是圆的舒服啊拿着一个方形的饮料瓶时间长了…

Docker最全教程之使用Docker搭建Java开发环境

前言 Java是一门面向对象的优秀编程语言&#xff0c;市场占有率极高&#xff0c;但是在容器化实践过程中&#xff0c;发现官方支持并不友好&#xff0c;同时与其他编程语言的基础镜像相比&#xff08;具体见各语言镜像比较&#xff09;&#xff0c;确实是非常臃肿。 Java [J…