文档章节

[笔记]改善Java程序的151个建议---第一章 Java开发中通用的方法和准则

jimyao
 jimyao
发布于 2016/01/29 14:45
字数 1975
阅读 10
收藏 0
点赞 1
评论 0

第一章 Java开发中通用的方法和准则

建议1:不要在常量和变量中出现易混淆的字母

字母“l”务必大写,字母“o”增加注释


建议2:莫让常量蜕变成变量

常量就是常量,在编译期必须确定其值,不应该在运行期更改,否则程序在运行期发生各种事情。

如:public static final int RAND_CONST = new Random().nextInt();


建议3:三元操作符的类型务必一致

类型不一致如:i < 100 : 90: 100.0(float)


建议4:避免带有变长参数的方法重载

变长参数,必须是方法的最后一个参数,一个方法不能定义多个变长参数。

避免变长参数重载,如下:

public void calPrice(int price, int discount)

public void calPrice(int price, int... discount)


建议5: 别让null值和空值威胁到变长方法

如:

public void method(String str, Integer... is)

public void method(String str, String... is)

client.method("China");

client.method("China", null);


正确做法:

String strs = null;

client.method("China", strs);


建议6:覆写变长方法也要遵循规矩

@Override必须满足如下条件:

从写方法不能缩小访问权限;

参数列表必须与被重写方法相同;(参数数量相同,类型相同,顺序相同)

返回类型必须与被重写的方法的相同或者是其子类;

重新方法不能抛新的异常,或者超出父类范围的异常,但是可以抛出更少,更有限的异常,或者不抛异常。


建议7:警惕自增的陷阱

错误语句,如:

int count = 0;

count= count++;  //结果是count的初始值0


建议8:不要让旧语法困扰你

goto语句

break,continue后面可以加上冒号做跳转,实现goto功能。


建议9:少用静态导入

如: import static java.lang.Math.PI


建议10:不要在本类中覆盖静态导入的变量和方法

//常量名誉静态导入的PI相同

public final static String PI="祖冲之";


建议11:养成良好习惯,显式声明UID

序列化标志接口

Serial Version ID流标识符(类的版本定义),如果没有的话,序列化和反序列化所对应的类版本发生了变化,JVM不能把数据流转换为实例对象。

private static final long serialVersionUID = *****L;

隐式声明会根据类的各种属性,方法,关系,类名,包名,参数,返回值等计算得出。


建议12:避免用序列化类在构造函数中卫不变量赋值(final)

static序列化时候根本没有保存到数据流中

下面错误,如:

public class Person implements Serializable{

     public final String name;

     Person(){

          name = "aa";

     }

}


建议13:避免为final变量复杂赋值

final变量赋值还有一种方式,通过方法赋值。

public final String  name = initName();


final会被重新赋值,是指简单对象,8个基本类型,数组,字符串(不通过new生成的String),但是不能方法赋值。


保存到磁盘(网络传输)上的对象文件包括2个部分:

类描述信息:包路径,继承关系,访问权限,变量描述,变量访问权限,方法签名,返回值,变量关联类信息。不记录方法,构造函数,static等。

transient,static的实例变量值

关联类也必须序列化


总结,反序列化时候final变量在以下情况下不会被重新赋值。

通过构造函数为final变量赋值

通过方法返回值为final变量赋值

final修饰的属性不是基本类型


建议14:使用序列化类的私有方法巧妙解决部分属性持久化问题

部分属性持久化,把不需要持久化的属性前面加上transient


姓名,基本工资可以序列化

绩效工资保密,不能序列化


实现了Serializable接口的类可以实现两个私有方法:writeObject和readObject。用来影响和控制序列化和反序列化的过程。

序列化的独有机制:序列化回调。Java调用ObjectOutputStream类把一个对象转换成流数据的时候,会通过反射检查被序列化的类是否有writeObject方法,并且检查其是否符合私有、无返回值的特征。如果有,则会委托该方法进行对象序列化。如没有,则由ObjectOutputStream按照默认规则继续序列化。readObject也一样。


import java.io.Serializable;



public class Salary implements Serializable {


        private static final long serialVersionUID = -5402065593284392992L;

        //基本工资

        private int basePay ;

        //绩效工资

        private int bonus ;

       

       Salary( int basePay , int bonus){

               this.basePay = basePay ;

               this.bonus = bonus ;

       }

       

        public int getBasePay() {

               return basePay ;

       }

       

        public void setBasePay(int basePay) {

               this.basePay = basePay ;

       }

       

        public int getBonus() {

               return bonus ;

       }

       

        public void setBonus(int bonus) {

               this.bonus = bonus ;

       }

       

       

}


import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;



public class Person implements Serializable{


        /**

        * Person serialVersionUID

        */

        private static final long serialVersionUID = 7592930394427200495L;

        //姓名

        private String name ;

        //薪水

        private transient Salary salary ;

       

       Person(String name, Salary salary){

               this.name = name ;

               this.salary = salary ;

       }


        public String getName() {

               return name ;

       }


        public void setName(String name) {

               this.name = name ;

       }


        public Salary getSalary() {

               return salary ;

       }


        public void setSalary(Salary salary) {

               this.salary = salary ;

       }

       

        //序列化委托方法

        private void writeObject(ObjectOutputStream out) throws IOException{

               out.defaultWriteObject();

               out.writeInt( this.salary .getBasePay());

       }

       

        //反序列化委托方法

        private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException{

               in.defaultReadObject();

               this.salary = new Salary(in.readInt(), 0);

       }

}


import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;



public class SerializationUtils {

        private static String FILE_NAME = "d:/a.bin";

        //序列化

        public static void writeObject(Serializable s) {

              ObjectOutputStream oos;

               try {

                      oos = new ObjectOutputStream(new FileOutputStream(FILE_NAME ));

                      oos.writeObject( s);

                      oos.close();

              } catch (FileNotFoundException e ) {

                      // TODO Auto-generated catch block

                      e.printStackTrace();

              } catch (IOException e ) {

                      // TODO Auto-generated catch block

                      e.printStackTrace();

              }


       }

       

        public static Object readObject(){

              Object obj = null;

               //反序列化

               try {

                     

                     ObjectInputStream input = new ObjectInputStream(new FileInputStream(FILE_NAME ));

                      obj = input.readObject();

                      input.close();

              } catch (IOException | ClassNotFoundException e ) {

                      // TODO Auto-generated catch block

                      e.printStackTrace();

              }

               return obj ;          

       }

}


//序列化Client

public class SerializeClient {


        public static void main(String[] args) {

               //基本工资1000,绩效工资25000

              Salary salary = new Salary(1000, 25000);

               //记录人员信息

              Person person = new Person("张三" , salary );

              SerializationUtils. writeObject(person);

       }


}


//反序列化

public class DeSerializationClient {


        public static void main(String[] args) {

               //反序列化并打印信息

              Person p = (Person)SerializationUtils. readObject();

              StringBuffer sb = new StringBuffer();

               sb.append( "姓名 : " + p .getName());

               sb.append( "\t基本工资: " + p .getSalary().getBasePay());

               sb.append( "\t绩效工资: " + p .getSalary().getBonus());

              System. out.println(sb );

       }

}


建议15:break万万不可忘
switch... case...
Performaces->Java->Compiler->Errors/Warnings->Potential Programming problems->'switch' case fall-through->Errors

建议16:易变业务使用脚本语言编写
脚步语言:灵活,便捷,简单。如Groovy

建议17:慎用动态编译

建议18:避免instanceof非预期结果
判断一个对象是否是一个类的实例

建议19:断言不是鸡肋
防御式编程中经常用断言Assertion对参数和环境做出判断,避免程序因不当的输入或错误的环境产生逻辑异常。断言是为调试程序而用。
assert默认是不启用的;assert抛出的异常AssertionErro是继承自Error。
防御式编程特点,所有外部因素都是邪恶的,存在企图摧毁程序的罪恶本源。为了抵制,要在程序中处处检验,设卡,不满足条件就不再执行后面的程序。保护主程序的正确性。
不能用断言在公开方法中做输入校验。
不能用断言在布尔表达式中执行逻辑代码

正确使用断言:按照正常执行逻辑不可能达到的代码区域放置断言
(1)私有方法中放置断言,作为输入参数的校验
(2)流程控制中不可能达到的区域,意义:程序执行到这里就是错误的。
(3)建立程序探针,断言变量之间的关系

建议20:不要只替换一个类
一个常量接口(类),编译器认为它是稳定态,所以编译时候直接把值编译到字节码中。以后无论怎么修改这个常量接口(类)里面的值,只要不重新编译,输出的还是原来的值。
发布应用系统时候,禁止使用类文件替换方式,整体WAR包发布是完全之策。
public class Constant{
     public final static int MAX_AGE = 100;
}


© 著作权归作者所有

共有 人打赏支持
jimyao
粉丝 17
博文 66
码字总数 27856
作品 0
朝阳
Oracle Java SE 8 发行版更新:限制商业或生产用途

Oracle Java SE 8 发行版更新 Oracle Java SE 8 的公开更新仍面向单独的个人使用提供,至少持续至 2020 年底。 2019 年 1 月以后发布的 Oracle Java SE 8 公开更新将不向没有商用许可证的业务...

抢小孩糖吃 ⋅ 04/18 ⋅ 61

Java语言标准(第10版)第一章(节选)翻译与评注

英文原文链接:https://docs.oracle.com/javase/specs/jls/se10/html/jls-1.html 评注是括在鱼尾号之间的文字,其余均为翻译 Java编程语言是一种通用目的的【有别于VBA、Matlab这些专用型语言...

Jelif ⋅ 06/02 ⋅ 0

有一到五年开发经验的JAVA程序员需要掌握的知识与技能!

JAVA是一种平台,也是一种程序设计语言,如何学好程序设计不仅仅适用于JAVA,对C++等其他程序设计语言也一样管用。有编程高手认为,JAVA也好C也好没什么分别,拿来就用。为什么他们能达到如此...

java高级架构牛人 ⋅ 06/02 ⋅ 0

Java编程基础知识点和技术点归纳

Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互...

Java小辰 ⋅ 05/23 ⋅ 0

Java虚拟机标准(第10版)第一章(节选)翻译与评注

英文原文链接:https://docs.oracle.com/javase/specs/jvms/se10/html/jvms-1.html 评注是括在鱼尾号之间的文字,其余均为翻译 Java虚拟机是Java平台的基石,这种技术实现了诸如跨平台、生成...

Jelif ⋅ 06/03 ⋅ 0

Java:大数据技术领域的一匹黑马

诞生于1991年的Java如今已经成为世界范围内应用最为广泛的编程语言之一。在今天的文章中,我们将共同了解Java所拥有的七大关键新特性,展望其如何在未来的超级计算、大数据以及物联网等领域继...

Java大数据处理 ⋅ 04/22 ⋅ 0

培训云计算学校,虚拟机基本结构讲解

我们要对JVM虚拟机的结构有一个感性的认知。毕竟我们不是编程人员,认知程度达不到那么深入。一个运行时的Java虚拟机实例的天职是:负责运行一个java程序。当启动一个Java程序时,一个虚拟机...

长沙千锋 ⋅ 05/17 ⋅ 0

Oracle Java Mission Control 帮助

缩写 含义 JDK Java 开发工具包 JDP Java Discovery Protocol JFR Java 飞行记录器 JMC Java Mission Control JMX Java Management Extensions JVM Java 虚拟机 MBean 托管 Bean (Java) RCP ......

光斑 ⋅ 04/27 ⋅ 0

RMI:Java中的分布式计算框架

RMI全称是Remote Method Invocation-远程方法调用,Java RMI在JDK1.1中实现的,其威力就体现在它强大的开发分布式网络应用的能力上,是纯Java的网络分布式应用系统的核心解决方案之一。其实...

qq_39521554 ⋅ 05/15 ⋅ 0

Java就业变难了?你需要对自己有点信心

伴随着IT的火热,越来越多的人进入了IT领域,这在进一步推动着IT发展的同时也极大增加了就业压力。伴随着激烈的岗位竞争,越来越多的人开始感叹工作难找,越火的行业越是如此,Java自是首当其...

糖宝_d864 ⋅ 06/08 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

10个免费的服务器监控工具

监控你的WEB服务器或者WEB主机运行是否正常与健康是非常重要的。你要确保用户始终可以打开你的网站并且网速不慢。服务器监控工具允许你收集和分析有关你的Web服务器的数据。 有许多非常好的服...

李朝强 ⋅ 28分钟前 ⋅ 0

压缩工具之zip-tar

zip 支持目录压缩。使用yum安装zip包,使用yum安装unzip包 zip 1.txt.zip 1.txt #将1.txt文件压缩,新生成的压缩文件为1.txt.zip,原文件保留 zip -r 123.zip 123/ #-r对目录操作。将123/目录...

ZHENG-JY ⋅ 29分钟前 ⋅ 0

Dubbo @Activate注解使用和实现解析

Activate注解标识一个扩展是否被激活和使用,可以放在定义的类上和方法上,dubbo用它在SPI扩张类定义上,标识这个扩展实现激活的条件和时机,先看下定义: /** * Activate * <p/> * ...

哲别0 ⋅ 36分钟前 ⋅ 0

6.5 zip压缩工具 tar打包 打包并压缩

1.tar tar命令格式 [-zjxcvfpP] filename tar -z:表示同时用gzip压缩。 -j:表示同时用bzip2压缩。 -J:表示同时用xz压缩。 -x:表示解包或者解压缩。 -t:表示查看tar包里的文件。 -c:表示建...

oschina130111 ⋅ 38分钟前 ⋅ 0

Linux系统工程狮养成记

如今的社会,随着时代的发展,出现了很多职业,像电子类,计算机类的专业,出现了各种各样的工程师,有算法工程师,java工程师,前端工程师,后台工程师,Linux工程师,运维工程师等等,不同...

六库科技 ⋅ 44分钟前 ⋅ 0

Linux 机器的渗透测试命令备忘表

如下是一份 Linux 机器的渗透测试备忘录,是在后期开发期间或者执行命令注入等操作时的一些典型命令,设计为测试人员进行本地枚举检查之用。 此外,你还可以从这儿(https://gbhackers.com/c...

寰宇01 ⋅ 46分钟前 ⋅ 0

windows 安装java开发环境,配置jdk

下载jdk安装文件 链接:https://pan.baidu.com/s/1UEKPjnAdMqNj612B39Pfsg 密码:ipqx 如果javac无法使用 1,检查环境变量名称中是否有空格。。。,去除后即可 2,将JAVA_HOME替换为原始路径...

阿豪boy ⋅ 47分钟前 ⋅ 0

简析log4j的实现方式

刚加入新公司,对日志的要求比较严格,对此特意花了几天时间看了一下log4j的源码,大概了解了一下log4j的实现方式,总结如下: log4j的实现分为两个步骤:log4j.xml的加载,logger的使用 这里...

zdatbit ⋅ 今天 ⋅ 0

win环境下jdk7与jdk8共存配置

1.jdk安装包 jdk安装包 安装步骤略 2.jdk等配置文件修改 在安装JDK1.8时(本机先安装jdk1.7再安装的jdk1.8),会将java.exe、javaw.exe、javaws.exe三个文件copy到了C:\Windows\System32,这...

泉天下 ⋅ 今天 ⋅ 0

windows profesional 2017 build problem

.net framework .... https://stackoverflow.com/questions/43330915/could-not-load-file-or-assembly-microsoft-build-frameworkvs-2017...

机油战士 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部