如何编写高效优雅 Java 程序
文章目录
- 编写高效优雅 Java 程序
- 面向对象
- 01、构造器参数太多怎么办?
- Builder 模式:
- 02、不需要实例化的类应该构造器私有
- 03、不要创建不必要的对象
- 04、避免使用终结方法
- 05、使类和成员的可访问性最小化
- 06、使可变性最小化
- 07、复合优先于继承
- 08、接口优于抽象类
- 方法
- 09、可变参数要谨慎使用
- 10、返回零长度的数组或集合,不要返回 null
- 11、优先使用标准的异常
- 通用程序设计
- 12、用枚举代替 int 常量
- 13、将局部变量的作用域最小化
- 14、精确计算,避免使用 float 和 double
- 15、当心字符串连接的性能
- 16、控制方法的大小
编写高效优雅 Java 程序
面向对象
01、构造器参数太多怎么办?
如果参数很多,会导致构造方法非常多,拓展性差,代码难编写,且难以看懂。
- 用 JavaBeans 模式
get 和 set
一行构造编程多行代码实现,需要使用额外机制确保一致性和线程安全。 - 用 builder 模式,
1、5 个或者 5 个以上的成员变量
2、参数不多,但是在未来,参数会增加
Builder 模式:
属于对象的创建模式,一般有
1、 抽象建造者:一般来说是个接口,包含 1)建造方法,建造部件的方法(不止一个),2)返回产品的方法
2、 具体建造者
3、 导演者,调用具体的建造者,创建产品对象
4、 产品,需要建造的复杂对象
对于客户端,创建导演者和具体建造者,并把具体建造者交给导演者,然后由客户端通知导演者操纵建造者进行产品的创建。 在实际的应用过程中,有时会省略抽象建造者和导演者。 优势:如果当大多数参数是可选时,代码易于阅读和编写,比 JavaBean 更加安全。
02、不需要实例化的类应该构造器私有
如,一些工具类提供的都是静态方法,这些类是不应该提供具体的实例的。可以参考 JDK 中的 Arrays。 好处:防止使用者 new 出多个实例。
03、不要创建不必要的对象
1、 避免无意中创建的对象,如自动装箱
可以在类的多个实例之间重用的成员变量,尽量使用 static。
性能对比。
但是,要记住,是不要创建不必要的对象,而不是不要创建对象。
对象池要谨慎使用,除非创建的对象是非常昂贵的操作,如数据库的连接,巨型对象等等
04、避免使用终结方法
finalizer 方法,jdk 不能保证何时执行,也不能保证一定会执行。如果有确实要释放的资源应该用 try/finally
05、使类和成员的可访问性最小化
模块对外部其他模块来说,隐藏其内部数据和其他实现细节——封装
编写程序和设计架构,最重要的目标之一就是模块之间的解耦。使类和成员的可访问性最小化无疑是有效的途径之一。 类似于微服务
06、使可变性最小化
尽量使类不可变,不可变的类比可变的类更加易于设计、实现和使用,而且更不容易出错,更安全。 常用的手段:
不提供任何可以修改对象状态的方法;
使所有的域都是 final 的。
使所有的域都是私有的。
使用写时复制机制。
07、复合优先于继承
继承容易破坏封装性,而且会使子类的实现依赖于父类。
复合则是在类中增加一个私有域,引用类的一个实例,这样的话就避免了依赖类的具体实现。
只有在子类确实是父类的一个子类型时,才比较适合用继承。
继承需要开发者对父类的结构有一定了解。
实际使用,如果肯定是父类的子类,使用继承,如果不很肯定,使用复合。
08、接口优于抽象类
接口只有方法申明,抽象类可以写方法的实现。
java 是个单继承的(不能继承多个抽象类),但是类允许实现多个接口。
所以当发生业务变化时,新增接口,实现接口只需要新增接口即可。但是抽象类有可能导致不需要变化的类也不得不实现新增的业务方法。
JDK 源码中常用的一种设计方法:定义一个接口,声明一个抽象的骨架类实现接口,骨架类类实现通用的方法,而实际的业务类可以同时实现接口又继承 骨架类,也可以只实现接口。
如 HashSet 实现了 implements Set 接口 但是又 extends 类 AbstractSet,而 AbstractSet 本身也实现了 Set 接口。其他如 Map,List 都是这样的设计的。
方法
09、可变参数要谨慎使用
可变参数是允许传 0 个参数的
如果是参数个数在 1~多个之间的时候,要做单独的业务控制。
具体代码不优雅。
10、返回零长度的数组或集合,不要返回 null
方法的结果返回 null,会导致调用方的要单独处理为 null 的情况。返回零长度,调用方可以统一处理,如使用 foreach 即可。
JDK 中也为我们提供了 Collections.EMPTY_LIST 这样的零长度集合
11、优先使用标准的异常
要尽量追求代码的重用,同时减少类加载的数目,提高类装载的性能
- 常用的异常
throw new IllegalArgumentException();//调用者传递的参数不合适
// throw new IllegalStateException();//接收的对象状态不对
// throw new UnsupportedOperationException();//不支持的操作
通用程序设计
12、用枚举代替 int 常量
声明的一个枚举本质就是一个类,每个具体的枚举值就是这个枚举类的实例。
- 使用常量容易在写代码时写错
- 使用常量如果要使用描述时比较麻烦
- 其他类使用常量时,类编译时会把常量值直接写到字节码中,如果常量值有变化,所有相关的类需要重新编译,否则会不可预料的错误
- 枚举高级:
枚举和行为绑定
所谓枚举的本质就是一个类,而枚举中定义的每一个具体的枚举类型其实就是这个枚举类的一个实例。 策略枚举:
13、将局部变量的作用域最小化
1、 在第一次使用的地方进行声明
2、 局部变量都是要自行初始化,初始化条件不满足,就不要声明
最小化的好处,减小局部变量表的大小,提高性能;同时避免局部变量过早声明导致不正确的使用。
14、精确计算,避免使用 float 和 double
float 和 double 在 JVM 存储的时候,有部分要做整数位,有部分要做小数位,所以存在精度上的问题 可以使用 int 或者 long 以及 BigDecimal
15、当心字符串连接的性能
在存在大量字符串拼接或者大型字符串拼接的时候,尽量使用 StringBuilder 和 StringBuffer
16、控制方法的大小
如何编写高效优雅 Java 程序相关推荐
- JVM性能调优5_编写高效优雅Java程序__享学课堂
面向对象: ü 构造器参数太多怎么办(5个以上)? 使用构造者模式(build), package com.xiangxue.ch04.builder01;public class FoodBuild ...
- 《Java 开发从入门到精通》—— 2.2 编写第一段Java程序
本节书摘来异步社区<Java 开发从入门到精通>一书中的第2章,第2.2节,作者: 扶松柏 , 陈小玉,更多章节内容可以访问云栖社区"异步社区"公众号查看. 2.2 编 ...
- 用java编写一个图书管理系统_手把手教你编写第一个java程序
安装完jdk后我们就可以试着编写第一个java程序了,让我们一起来试试吧! 第一步 点击开始--所有程序--附件--记事本,新建记事本,输入以下代码: class HelloWorld { publi ...
- 编写第一个Java程序:helloworld
配置好java开发环境后,我们可以编写第一个java程序(helloworld). 在开始编写java程序时,我们要知道java程序开发的三个步骤:编写.编译.运行. 编写阶段主要是由程序员编写后缀为 ...
- 编写一个简单Java程序,计算银行年存款的本息
编写一个简单Java程序,计算银行年存款的本息 要求:程序运行后要求用户输入存款本金.年利率和存款年限,最后程序计算并输出相应年限后存款的金额.相应的计算公式为:存款总额=本金 * (1 + 利率)存 ...
- 用记事本编写第一个Java程序运行时 出现报错:错误: 类helloworld是公共的, 应在名为 helloworld.java 的文件中声明 public class helloworld {
在书本上盲人摸象的摸索学习Java,Java环境配置完成,安装好eclipse后,便兴冲冲的去在记事本上编写第一个Java程序,结果给破了一盆冷水,略懵 public class helloworld ...
- eclipse编写java教程_【安装eclipse, 配置java环境教程】 编写第一个java程序
写java通常用eclipse编写,还有一款编辑器比较流行叫IJ.这里我们只说下eclipse编写java的前期工作. 在安装eclipse之前要下载java的sdk文件,即Java SE Devel ...
- 编写高效的java代码
供稿人:肖华飚 概述 随着Java的广泛应用,越来越多的关键企业系统也使用Java构建.作为Java核心运行环境的Java虚拟机JVM被广泛地部署在各种系统平台上.对Java应用的性能优化也越来越受到 ...
- 【读书笔记】《编写高效的JavaScript程序》
为什么80%的码农都做不了架构师?>>> 看到一篇文章,http://www.csdn.net/article/2012-11-20/2811887-writing-fast- ...
最新文章
- android系统二次开发,Andorid系统二次开发界面
- JavaScript是如何工作的:与WebAssembly比较及其使用场景
- NuGet学习笔记(1)——初识NuGet及快速安装使用
- [收集] 经典C/C++面试题(三)
- strncpy与strcpy的区别与注意事项
- Javascript -- In
- [转载]析构函数的虚析构和非虚析构调用的差别
- poj2060Taxi Cab Scheme(二分图匹配)
- (98)FPGA时序裕量
- JavaScript数组filter方法
- NOIP5424. 【NOIP2017提高A组集训10.25】凤凰院凶真 LCIS 方案
- 《炒股的智慧》--陈江挺
- 普元与达梦的多数据源配置
- Arch-01-02-互联网产品设计常用文档类型 BRD、MRD、PRD、FSD
- Android入门第30天-Android里的Toast的使用
- 安装蓝牙驱动IVT BlueSoleil找不到蓝牙硬件的解决办法
- Vue7 异步加载 懒加载
- 解决Apache提示没有权限访问的问题
- C++原创飞机大战代码
- 什么是wifi霸屏神器?用WiFi霸屏广告机打广告是什么体验?
热门文章
- 最短寻道时间优先算法c语言程序,操作系统先来先服务、最短寻道时间优先(SSTf)、扫描算法(SCAN)、循环扫描算法(CSCAN)的c++实现.doc...
- gpg加密命令 linux_Ubuntu下加密命令GPG和KEY
- ruby 数据类型Symbol
- NodeJS + Sequelize + Mysql + Vue + Bootstrap
- computed、watch和methods特性比较
- jsoncpp的安装与使用实战(windows交叉编译Ubuntu)
- 如何加快C++代码的编译速度
- 模拟ARP报文发送,通过改变拓扑结构,观察报文发送方法以及途径
- 剑指offer十八之二叉树的镜像
- eclipse-阶段二-字体修改问题