java可以返回微妙吗_Java开发中10个最为微妙的最佳编程实践
这是10个最佳实践的列表,比你平时在Josh Bloch的《effective java》中看到的规则更加精妙。和Josh Bloch列出的非常容易学习的、和日常情况息息相关的实践相比,这个列表中提到了一些关于设计API/SPI的实践,虽然不常见,但是存在很大的效率问题。
我在编写和维护jOOQ(一种内部DSL,在java中将SQL模块化)时,碰到了这些问题。作为内部DSL,jOOQ最大限度的挑战了java编译器和泛型,把泛型,变量和重载结合到了一起。这种太宽泛的API是Josh Bloch相当不推荐的。
让我来和你分享这10个java编码中微妙的最佳实践:
1.牢记C++的析构函数
还记得C++中的析构函数吗?不记得了?或许你真的很幸运,因为你再也不必为删除对象后,没有及时释放内存而造成内存泄露进行调试了。我们真的应该感谢Sun和Oracle实现垃圾回收机制。
尽管如此,对于我们来说,析构函数仍然有一个很有趣的特点。它常常会让我们对以和分配内存相反的顺序释放内存的工作模式感到容易理解。同样,在JAVA代码中,当你处理如下类析构函数语法的时候,也要把这个特性牢记在心:
• 当使用@Before和@After但与注解时;
• 当分配和释放JDBC资源时;
• 当调用父类的方法时。
也有其他不同的使用案例。这有一个显示如何实现事件监听的实例:
@Overridepublicvoid beforeEvent(EventContext e) {
super.beforeEvent(e);//Super code before my code
}
@Overridepublicvoid afterEvent(EventContext e) {//Super code after my code
super.afterEvent(e);
}
法则:无论何时,当你使用before/after, allocate/free, take/return语法实现逻辑时,仔细想想是否需要反序的使用after/free/return操作。
2. 不要相信你早期的SPI演进判断
为使用者提供SPI可以很容易让他们注入自定义行为到你的库/代码。当心你的SPI演进判断可能会迷惑你,让你认为(不)需要附加的参数。当然,不应该过早的添加功能。但是一旦你发布了SPI,一旦你决定遵循语义版本,当你发现你可能在某些情况下需要另外一个参数时,你将真的后悔为SPI添加了一个愚蠢的单参数方法:
interface EventListener {//Bad
void message(Stringmessage);
}
如果你也需要消息ID和消息源,怎么办?对于上面的类型,API演进将会阻碍你添加参数。当然,有了Java8,你可以添加一个defender方法,“防御”你早期糟糕的设计决策:
interface EventListener {//Bad
default void message(Stringmessage) {
message(message,null,null);
}//Better?
void message(Stringmessage,Integerid,
MessageSource source
);
}
注意很不幸defender方法不能为final。
但是比起用数十个方法污染你的SPI,使用一个上下文对象(或参数对象)好很多。
interface MessageContext {Stringmessage();Integerid();
MessageSource source();
}
interface EventListener {//Awesome!
void message(MessageContext context);
}
比起EventListner SPI你可以更容易演进MessageContext API,因为很少用户会实现它。
规则: 无论何时你指定SPI的时候, 考虑使用上下文/参数对象,而不要编写固定参数数量的方法。
备注: 使用特定的MessageResult类型传递结果也是一个好的想法,该类型可以通过构造器API构建。这将会为你的SPI提供更多的SPI演进灵活性。
3.避免使用匿名,局部或内部类
Swing程序员通常只要按几下快捷键即可生成成百上千的匿名类。在多数情况下,只要遵循接口、不违法SPI子类型的生命周期(SPI subtype lifecycle),这样做也无妨。
但是不要因为一个简单的原因——它们会保存对外部类的引用,就频繁的使用匿名、局部或者内部类。因为无论它们走到哪,外部类就得跟到哪。例如,在局部类的域外操作不当的话,那么整个对象图就会发生微妙的变化从而可能引起内存泄露。
规则:在编写匿名、局部或内部类前请三思能否将它转化为静态的或普通的顶级类,从而避免方法将它们的对象返回到更外层的域中。
注意:使用双层花括号来初始化简单对象:
newHashMap() {{
put("1","a");
put("2","b");
}}
这个方法利用了 JLS §8.6规范里描述的实例初始化方法(initializer)。表面上看起来不错,但实际上不提倡这种做法。因为要是使用完全独立的HashMap对象,那么实例就不会一直保存着外部对象的引用。此外,这也会让类加载器管理更多的类。
java可以返回微妙吗_Java开发中10个最为微妙的最佳编程实践相关推荐
- java 判断手机运营商_Java开发中识别手机运营商的方法
在Java开发中程序需要根据用户输入的号码判断运营商,这该怎么实现呢?而我们需要根据不同的运营商进行相应的处理,下面是爱站技术频道小编介绍的Java开发中识别手机运营商的方法. js实现方法: var ...
- java安装_Java开发中更多常见的危险信号
java安装 在< Java开发中的常见危险信号>一文中,我介绍了一些不一定本身就是错误或不正确的做法,但它们可能表明存在更大的问题. 这些"红色标记"类似于" ...
- java遍历对象属性_java开发中遍历一个对象的所有属性并set值 缓存优化
今天技术之家陪你一起了解java开发中遍历一个对象的所有属性并set值 缓存优化: Java反射 1.创建缓存池,可以加快访问速度private static final Map> CACHE ...
- java开发常用jar包_Java开发中常用jar包整理及使用
本文整理了我自己在Java开发中常用的jar包以及常用的API记录. 一.common-lang3 简介:一个现在最为常用的jar包,封装了许多常用的工具包 依赖: org.apache.common ...
- java 绑定微信号开发_Java开发中的更多常见危险信号
java 绑定微信号开发 在< Java开发中的常见危险信号>一文中,我研究了一些不一定本身就是错误或不正确的做法,但它们可能表明存在更大的问题. 这些"红色标记"类似 ...
- java 绑定微信号开发_Java开发中的常见危险信号
java 绑定微信号开发 在开发,阅读,复审和维护成千上万行Java代码的几年中,我已经习惯于看到Java代码中的某些" 危险信号 ",这些信号通常(但可能并非总是)暗示着代码有问 ...
- java 逻辑或 作用_Java开发中与之间的区别,你真的知道吗?
&与&& 首先来讲一下&&,这个在java逻辑运算符里面被称为短路与,它与&逻辑与只差了一个& ,但是区别却很大,它的作用是如果前面的表达式运行 ...
- java静态引用_Java开发中静态方法引用和实例方法引用案例详细讲解
Java开发 前言 在Java的日常开发中静态方法引用和实例方法引用在很多地方都会用到,可以说是万金油,但是你真的掌握了吗?下面就由小编给大家做一个比较细想的讲解,废话不多说现在开始把. 正文 大家对 ...
- java 开发模式详解_Java开发中的23种设计模式详解4
其实每个设计模式都是很重要的一种思想,看上去很熟,其实是因为我们在学到的东西中都有涉及,尽管有时我们并不知道,其实在Java本身的设计之中处处都有体现,像AWT.JDBC.集合类.IO管道或者是Web ...
最新文章
- 2 OC 对象的本质(一个Student 占用的内存大小)
- Websphere MQ 开发实例
- 详解英伟达三大专业视觉解决方案,覆盖数据中心和边缘计算
- NDN与TCP/IP
- Linux——安装FTP服务器
- PHP敏感词过滤【整理实践版】
- 【动态规划】LeetCode 1143最长公共子序列
- Windows Server 2012虚拟桌面分辨率支持列表
- 深度学习常用数据集汇总
- java实现图片去除底色,图片变成透明背景
- js进行txt文件下载方式或oss文件访问下载跨域解决
- 怎么在图片上直接编辑文字?建议收藏这些编辑方法
- 关于计算机知识的动画电影,动画概论总复习题目(附答案)
- 普通程序员如何走出困境?
- 如何使用Windows Live Writer远程发布到WordPress
- mp3与wav格式的互转
- 基于深度学习的印刷电路板瑕疵识别
- 【Teradata】数据库初始化(sysinit和dip工具)
- Swiper实现两种常用轮播图
- ushort java_Java UShort类代码示例
热门文章
- jquery ui tabs详解(中文) 【转载】
- Mybatis源码阅读(三):结果集映射3.3 —— 主键生成策略
- Mybatis源码阅读(二):动态节点解析2.2 —— SqlSourceBuilder与三种SqlSource
- su oracle c expdp,expdp/impdp 数据泵导入导出
- [转载] Java StringBuilder StringJoiner
- [转载] 【Java】将一个字符串的字符排序,按ASCII表的顺序从小到大
- [转载] python类运算符的重载
- Java ArrayList removeRange()方法与示例
- avr计数_使用8位LCD创建计数器| AVR
- Java ObjectOutputStream writeInt()方法及示例