咨询热线:15242638876 联系人:尼玛次仁 地址:霸州市经济开发区56号
编写高质量代码:改善Java程序的151个建议 --[36~51]
来源:esball世博合法吗 发布时间:2019-11-22 点击量:53
编写高质量代码:改善Java程序的151个建议 --[36~51]
工具类不可实例化
工具类的方法和属性都是静态的,不需要生成实例即可访 问,而且JDK也做了很好的处理,由于不希望被初始化,于是就设置了构造函数private的访问权限,表示出了类本身之外,谁都不能产生一个实例:
class UtilsClazz{ public UtilsClazz(){ throw new Error("Don"t instantiate "+getClass()); }}
避免对象的浅拷贝
super.clone()的拷贝规则:
- 基本类型:如果变量是基本类型,则拷贝其值。比如int、float等对 象:如果变量是一个实例对象,则拷贝其地址引用,也就是说此时拷贝出的对象与原有对象共享该实例变量,不受访问权限的控制,这在Java中是很疯狂的,因 为它突破了访问权限的定义:一个private修饰的变量,竟然可以被两个不同的实例对象访问,这让java的访问权限体系情何以堪。String字符串:这个比较特殊,拷贝的也是一个地址,是个引用,但是在修改时,它会从字符串池(String pool)中重新生成新的字符串,原有的字符串对象保持不变,在此处我们可以认为String是一个基本类型。
使用序列化对象的拷贝
要求要拷贝的对象必须实现了Serializable接口。
import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;public final class CloneUtils { private CloneUtils() { throw new Error(CloneUtils.class + " cannot instance "); } // 拷贝一个对象 public static <T extends Serializable> T clone(T obj) { // 拷贝产生的对象 T cloneObj = null; try { // 读取对象字节数据 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(cloneObj); oos.close(); // 分配内存空间,写入原始对象,生成新对象 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); // 返回新对象, 并做类型转换 cloneObj = (T) ois.readObject(); ois.close(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return cloneObj; }}
通过CloneUtils工具进行对象的深拷贝了,用词方法进行对象拷贝时需要注意两点:
对象的内部属性都是可序列化的:如果有内部属性不可序列化,则会抛出序列化异常,这会让调试者很纳闷,生成一个对象怎么回出现序列化异常呢?从这一点考虑,也需要把CloneUtils工具的异常进行细化处理。注 意方法和属性的特殊修饰符:比如final,static变量的序列化问题会被引入对象的拷贝中,这点需要特别注意,同时 transient变量(瞬态变量,不进行序列化的变量)也会影响到拷贝的效果。当然,采用序列化拷贝时还有一个更简单的方法,即使用Apache下的 commons工具包中SerializationUtils类,直接使用更加简洁.
package org.apache.commons.lang3; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.OutputStream; import java.io.Serializable; import java.util.HashMap; import java.util.Map; public class SerializationUtils { public SerializationUtils() {} //克隆一个序列化对象 public static <T extends Serializable> T clone(T object) { } //执行串行往返也就是执行序列化或者反序列化 public static <T extends Serializable> T roundtrip(T msg) { return (Serializable)deserialize(serialize(msg)); } //讲一个对象序列化并且输出到输出流中 public static void serialize(Serializable obj, OutputStream outputStream) { Validate.isTrue(outputStream != null, "The OutputStream must not be null", new Object[0]); try { ObjectOutputStream out = new ObjectOutputStream(outputStream);Throwable localThrowable2 = null; try { out.writeObject(obj); } catch (Throwable localThrowable1) { localThrowable2 = localThrowable1;throw localThrowable1; } finally { if (out != null) if (localThrowable2 != null) try { out.close(); } catch (Throwable x2) { localThrowable2.addSuppressed(x2); } else out.close(); } } catch (IOException ex) { throw new SerializationException(ex); } } //将一个对象序列化并返回字节数组 public static byte[] serialize(Serializable obj) { ByteArrayOutputStream baos = new ByteArrayOutputStream(512); serialize(obj, baos); return baos.toByteArray(); } //讲一个输入流反序列化成一个对象 public static <T> T deserialize(InputStream inputStream) { } //将一个字节数组反序列化成一个对象 public static <T> T deserialize(byte[] objectData) { Validate.isTrue(objectData != null, "The byte[] must not be null", new Object[0]); return deserialize(new ByteArrayInputStream(objectData)); } static class ClassLoaderAwareObjectInputStream extends ObjectInputStream { private static final Map<String, Class<?>> primitiveTypes = new HashMap(); private final ClassLoader classLoader; static { primitiveTypes.put("byte", Byte.TYPE); primitiveTypes.put("short", Short.TYPE); primitiveTypes.put("int", Integer.TYPE); primitiveTypes.put("long", Long.TYPE); primitiveTypes.put("float", Float.TYPE); primitiveTypes.put("double", Double.TYPE); primitiveTypes.put("boolean", Boolean.TYPE); primitiveTypes.put("char", Character.TYPE); primitiveTypes.put("void", Void.TYPE); } ClassLoaderAwareObjectInputStream(InputStream in, ClassLoader classLoader) throws IOException { super(); this.classLoader = classLoader; } protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String name = desc.getName(); try { return Class.forName(name, false, this.classLoader); } catch (ClassNotFoundException ex) { try { return Class.forName(name, false, Thread.currentThread().getContextClassLoader()); } catch (ClassNotFoundException cnfe) { Class<?> cls = (Class)primitiveTypes.get(name); if (cls != null) { return cls; } throw cnfe; } } } } }
覆写equals方法必须覆写hashCode方法
class Person{ @Override public int hashCode() { return new HashCodeBuilder().append(name).toHashCode(); } }
其中HashCodeBuilder是org.apache.commons.lang.builder包下的一个哈希码生成工具;org.apache.commons.lang.builder包下相关资料参考学习:http://www.blogjava.net/19851985lili/articles/95448.html
推荐覆写toString方法(ToStringBuilder或者自己重写toString())
使用package-info类为包服务
- 声明友好类和包内访问常量:这个比较简单,而且很实用,比如一个包中有很多内部访问的类或常量,就可以统一放到package-info类中,这样很方便,便于集中管理,可以减少友好类到处游走的情况;
class PkgClazz { public void test() { } } class PkgConstant { static final String PACKAGE_CONST = "ABC"; }
- 为在包上提供注解提供便利:比如我们要写一个注解(Annotation),查看一下包下的对象,只要把注解标注到package-info文件中即可,而且在很多开源项目中也采用了此方法,比如struts2的@namespace、hibernate的@FilterDef等。提供包的整体注释说明:如果是分包开发,也就是说一个包实现了一个业务逻辑或功能点或模块或组件,则该包需要一个很好的说明文档,说明这个包是做什么用的,版本变迁历史,与其他包的逻辑关系等,package-info文件的作用在此就发挥出来了,这些都可以直接定义到此文件中,通过javadoc生成文档时,会吧这些说明作为包文档的首页,让读者更容易对该包有一个整体的认识。当然在这点上它与package.html的作用是相同的,不过package-info可以在代码中维护文档的完整性,并且可以实现代码与文档的同步更新。
不要主动进行垃圾回收
相关产品
-
韩国已经连续5年在这份榜单上排名榜首,进入21世纪后,该公司市值最高的企业三星电子已经在美国获得的专利数量在全世界所有企业中排名第二,仅仅次于IBM。另外该公司的半导体、智能手机和数字媒体设备业务在韩国已经形成了生态,整合了韩国国内的供应商。
-
不少人认为,喝香槟一定要用笛形杯,其实不然。笛形杯看起来十分优雅,且多在庆祝的场合出现,其狭窄的杯口能够防止其中的气泡消散得太快,而长长的杯身则方便你观察气泡上升的过程。然而,它的小杯口却不利于香槟散发其香气,给我们的闻香带来不便。一些餐厅会选择用白葡萄酒杯来装盛香槟,因为这种杯子杯身较宽,杯口窄小,有利于酒液充分与氧气接触,释放香气。
-
但另一方面,特朗普和共和党也存在“自毁长城”的可能性。上月就已锁定共和党提名的特朗普,虽努力“团结全党”却收效甚微。而且他并未明显收敛以往的出格言论,近日又因批评一位联邦法官的墨西哥裔背景而深陷“种族歧视门”,其言论引起共和党大佬齐声反对,更被众议长瑞安指责是“教科书式的种族主义言论”。如果特朗普继续沿着这条路走下去,他将不仅冒犯更多选民,进一步分裂共和党,更是给希拉里送上一份“厚礼”,亲手把她送进白宫。(完)
-
2013佛光杯大学女子篮球邀请赛25日在高雄巨蛋进行预赛,吴敦义(前右起)、“行政院政务委员”杨秋兴 、佛光山副住持慧传法师等人观战,为选手加油。台湾“中央社”图
-
除了大火的 IP,腾讯游戏也确实在大火的区块链领域插了一脚。腾讯发布了它的第一款区块链游戏,不是区块链养企鹅,叫做《一起来捉妖》。
-
出道以来,王珞丹因为出演的角色,常常为媒体或观众冠以“小妞”的称号,对于自我定位,她打趣说:“多元化、演技派、实力派、老艺术家。”
-
“很快,我们将生活在一个人人都可以身临其境般分享和体验全部场景的世界,”扎克伯格在近期的世界移动通信大会(MWC)上说。“想象一下,你可以在任何时候你都可以坐在篝火前,与朋友待在一起;或者在任何时间都可以与朋友们在私人电影院看电影。想象下在全球任意一个角落开会或举办大会。所有这些都将成为现实,这也是为什么Facebook这么早在大力投资虚拟现实,我们真的很希望提供这些社交体验。”
-
所以,我又要来念叨那句话了,请大家不要不耐烦:汽车只是个工具而已,没必要那么爱惜。如果为了省点油,至少请用中等油门加速吧。
热点资讯
- 原来山寨电视机是这么生产出来的:从番禺大石走向电商平台2019-06-26
- 农业发展银行向西藏贷款780亿元,重点是扶贫和艰苦奋斗。2019-11-14
- 分析师:对抗亚马逊,谷歌应给每个用户送一台HomeMini2019-11-05
- “泰山之夜”2019泉城新年音乐会如期相约2019-06-26
- 央视、新华社批苹果AppStore:审核不严,系统存漏洞2019-11-17
- 한국야구금메달2019-06-26
- 《星球大战9》今夏开拍:《美国谍梦》主角凯丽·拉塞尔加盟2019-11-21
- [톱플레이]마지막에웃는게진짜웃는거야!外2019-06-26