Java开发中通用的方法和准则。

  • 不要在常量和变量中出现易容易混淆的字母

        注意:字母“l”作为长整形标志时务必大写。

  • 莫让常量蜕变成变量

        注意:务必让常量的值在运行器保持不变。

  • 三元操作符的类型务必一致。

        三元操作符类型的转换规则:

        1、若两个操作数不可转换,则不做转换,返回值为Object类型。

        2、若两个操作数是明确类型的表达式(比如变量),则按照正常的二进制数字来转换,int类型转换为long类型,long类型转换为float类型等。

        3、若两个操作数中有一个是数字S,另外一个是表达式,且其类型标示为T,那么,若数字S在T的范围内,则转换为T类型;若S超出了T类型的范围,则T转换为S类型。

        4、若两个操作数都是直接量数字(Literal),则返回值类型为范围较大者。

  • 避免带有变长参数的方法重载

        int是一个原生数据类型,而数组本身是一个对象,编译器想要“偷懒”,于是他会从最简单的开始“猜想”,只要符合编译条件的即可通过。

  • 别让null值和控制威胁到变长方法
  • 覆写变长方法也循规蹈矩

        覆写必须满足的条件:

            1、重写方法不能缩小访问权限。

            2、参数列表必须与被重写方法相同。

            3、返回类型必须与被重写方法的相同或是其子类。

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

        注意:覆写的方法参数与父类相同,不仅仅是类型、数量,还包括显示形式。

  • 警惕自增的陷阱

        count++是一个表达式,是有返回值的,他的返回值就是count自加前的值,Java对自加是这样处理的:首先把count的值(注意是值,不是引用)拷贝到一个临时变量区,然后对count变量加1,最后返回临时变量区的值。

  • 不要让旧语法困扰你
  • 少用静态导入

        对于静态导入,一定要遵循两个规则:

        1、不使用*(星号)通配符,除非是导入静态常量类(只包含常量的类或接口)。

        2、方法名是具有明确、清晰表象意义的工具类。

  • 不要在本类中覆盖静态导入的变量和方法

        编译器有一个“最短路径”原则:如果能够在本类中查找到的变量、常量、方法,就不会到其他包或父类、接口中查找,以确保本类中的属性、方法优先。

  • 养成良好习惯,显示声明UID

        注意:显示声明serialVersionUID可以避免对象不一致,但尽量不要以这种方式向JVM“撒谎”。

 

  • 避免用序列化类在构造函数中为不变量赋值

 

        final属性是一个直接量,在反序列化时就会重新计算。

        反序列化的基本规则:

            1、保持新旧对象的final变量相同,有利于代码业务逻辑统一。

            2、反序列化时构造函数不会执行。

        反序列化的执行过程是这样的:JVM从数据流中获取一个Object对象,然后根据数据流中的类文件描述信息(在序列化时,保存到磁盘的对象文件中包含了类描述信息,注意,是类描述信息,不是类)查看,发现是final变量,需要重新计算。

        注意:在序列化类中,不使用构造函数为final变量赋值。

  • 避免为final变量复杂赋值

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

            1、类描述信息

                包括包路径、继承关系、访问权限、变量描述、变量访问权限、方法签名、返回值,以及变量的关联类信息。要注意的一点是,他并不是class文件的翻版,他不记录方法、构造函数、static变量等的具体体现。之所以类描述会被保存、很简单,是因为能去也能回,这保证反序列化的健壮运行。

            2、非瞬态(transient关键字)和非静态(static关键字)的示例变量值

                注意,这里的值如果是一个基本类型,好说,就是一个简单值保存下来:如果是复杂对象,也简单,连该对象和关联类信息一起保存,并且持续递归下去(关联类也必须实现Serializable接口,否则会出现序列化异常),也就是说递归到最后,其实还是基本数据类型的保存。

        反序列化时final变量在以下情况下不会重新赋值:

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

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

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

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

        序列化独有的机制:序列化回调。Java调用ObjectOutputStream类把一个对象转换成流数据时,会通过反射(Reflection)检查被序列化的类是否有writeObject方法,并且检查其是否符合私有、无返回值的特性。若有,则会委托该方法进行对象序列化,若没有,则由ObjectOutputStream按照默认规则继续序列化。同样,在从流数据恢复成实例对象时,也会检查是否有一个私有的readObject方法,如果有,则会通过该方法读取属性值。此处有几个关键点要说明:

        1、out.defaultWriteObject()

        告知JVM按照默认规则写入对象,惯例的写法是写在第一句话里。

        2、in.defaultReadObject()

        告知JVM按照默认规则读入对象,惯例的写法也是写在第一句话里。

        3、out.writeXX和in.readXX

        分别是写入和读出相应的值,类似一个队列,先进先出,如果此处有复杂的数据逻辑,建议按封装Collection对象处理。

  • break万万不可忘

    最简单的解决办法:修改IDE的警告级别,例如在Eclipse中,可以依次点击PerFormaces→Java→Compiler→Errors/Warnings→Potential Programming problems,然后修改'switch' case fall-through为Errors级别,如果你胆敢不在case语句中加入break,那Eclipse直接报个红叉给你看,这样就可以完全避免该问题的发生了。

  • 易变业务使用脚本语言编写
  • 慎用动态编译

        在使用动态编译时,需要注意以下几点:

        1、在框架中谨慎使用

        2、不要在要求高性能的项目使用

        3、动态编译要考虑安全问题

        4、记录动态编译过程

  • 避免instanceof非预期结果
  • 断言绝不是鸡肋

        assert有以下两个特性:

            1、默认是不启动的

            2、抛出的异常AssertionError是继承自Error的

        以下两种情况不可使用:

            1、在对外公开的方法中

            2、在执行逻辑代码的情况下

        按照正常执行逻辑不可能到达的代码区域可以放置assert。具体分为三种情况:

            1、在私有方法中放置assert作为输入参数的校验

            2、流程控制中不可能达到的区域

            3、建立程序探针

  • 不要只替换一个类

        对于final修饰的基本类型和String类型,编译器会认为他是稳定态(Immutable Status),所以在编译时就直接把值编译到字节码中了,避免了在运行器引用(Run-time Reference),以提高代码的效率。

        对于final修饰的类(即非基本类型),编译器认为他是不稳定态(Mutable Status),在编译时建立的则是引用关系(该类型也叫做Soft Final),如果CLient类引入的常量是一个类或实例,即使不重新编译也会输出最新值。

        注意:发布应用系统时禁止使用类文件替换方式,整体WAR包发布才是万全之策。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

软件求生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值