热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:Java代码常见优化方案

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java代码常见优化方案相关的知识,希望对你有一定的参考价值。Java代码常见优化方案首先,良好的编码规

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java代码常见优化方案相关的知识,希望对你有一定的参考价值。



Java代码常见优化方案

首先,良好的编码规范非常重要。在 java 程序中,访问速度、资源紧张等问题的大部分原因,都是代码不规范造成的。

单例的使用场景
单例模式对于减少资源占用、提高访问速度等方面有很多好处,但并不是所有场景都适用于单例。
简单来说,单例主要适用于以下三个方面:

多线程场景,通过线程同步来控制资源的并发访问。
多线程场景,控制数据共享,让多个不相关的进程或线程之间实现通信(通过访问同一资源来控制)。
控制实例的产生,单例只实例化一次,以达到节约资源的目的;

不可随意使用静态变量
当某个对象被定义为 static 变量,那么 GC 通常是不会回收这个对象所占有的内存。
示例如下:
public class A {
private static B b = new B();
}
此时静态变量 b 的生命周期与 A 类同步,即如果 A 类不卸载,b 对象会常驻内存,直到程序终止。

创建 Java 对象使用注意事项
根据业务使用场景,尽量避免在循环中 new 对象。

这是因为系统要花费时间来创建对象,而且还要花时间对这些对象进行管理和垃圾回收。所以在可以控制的范围内,尽量保证最大限度地重用对象,最好能用基本的数据类型或数组来替代对象。

final 修饰符使用注意事项

final 修饰符的类是不可派生的,即不可被继承。在 java 核心代码中,有很多 被 final 修饰的类,如 java.lang.String 类。

如果一个类是 final 的,则该类所有方法都是 final 的。java 编译器会寻找机会内联(inline)所有的 final 方法,这与具体的编译器实现有关。这样做能够使性能平均提高 50% 。
class A {
public void setSize (int size) {
this.size = size;
}
private int size;
}
// setSize 方法变为 final ,性能更好
class A {
final public void setSize (int size) {
this.size = size;
}
private int size;
}

让访问实例变量的 getter/setter 方法变成 final:简单的 getter/setter 方法应该被置成 final ,这会告诉编译器此方法不会被重载,可以变成 ”inlined” 。

局部变量使用规范
调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快;其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。

处理好包装类型和基本类型的使用场所
基本类型:byte,short,int,long,float,double,char,boolean
对应包装类型:Byte,Short,Int,Long,Float,Double,Character,Boolean

基本类型和包装类型在使用过程中可以相互转换,但它们所产生的内存区域是完全不同的。基本类型的产生和处理都在栈中处理,包装类型是引用类型,其对象是在堆中产生实例。

在集合类对象,有对象方面需要的处理使用包装类型合适,其他情况的处理提倡使用基本类型。

使用基本数据类型代替对象
String s1 = "hello";
这种方式会创建一个 “hello” 字符串,而且 JVM 的字符缓存池会缓存这个字符串。
String s2 = new String("hello");

这种方式除了创建字符串外,s2 所引用的 String 对象底层包含一个 char[] 数组,其中依次存放了 h,e,l,l,o 。

synchronized 使用规范
实现同步需要很大的系统开销作为代价的,甚至可能造成死锁。所以尽量避免无谓的同步控制。
synchronize 方法被调用时会直接把当前对象锁住,在该方法执行完之前其他线程无法调用当前对象的其它方法。比较灵活的用法是使用代码块同步代替在方法中同步。

finalize使用规范
不要将资源清理放在 finalize 方法中完成,这种方法也很少使用。
由于 GC 的工作量很大,尤其是回收 Young 代内存时,大都会引起应用程序暂停。如果选择使用 finalize 方法进行资源清理,会导致 GC 负担加大,程序运行效率变差。
不需要线程同步,应尽量使用 HashMap 、ArrayList
HashTable 、Vector 等使用了同步机制,导致降低。

HashMap 使用规范
创建一个比较大的 hashMap 时,应该使用带有参数的构造函数创建对象。
示例如下:
public HashMap(int initialCapacity, float loadFactor);
hash 扩容是一件很耗费性能的事,默认构造函数创建的对象的 initialCapacity 只有 16,loadFactor 是 0.75 ,最好准确的估计所需要的最佳大小。同样对于 Hashtable ,Vectors 也是如此。

减少对变量的重复计算
for (int i = 0; i // 应该改为
for (int i=0, l=list.size(); i

避免不必要的创建对象
A a = new A();
if (i == 1) {
list.add(a);
}
// 应该改为
if (i == 1) {
A a = new A();
list.add(a);
}

finally 使用规范
在 try-catch 里,使用到的资源要能够被释放,以避免资源泄漏,这最好在 finally 块中去做。无论程序执行是否有异常,finally 里的代码总是会执行的,这样可以确保资源的正确关闭。

StringBuffer使用规范
StringBuffer 的无参构造函数会创建一个默认 16 的字符数组。在使用过程中,如果数组长度超出 16 ,就要重新分配内存,创建一个容量更大的数组,并将原先的数组复制过来,再丢弃旧的数组。

在多数情况下,可以在创建 StringBuffer 的时候指定大小,避免了在容量不够的时候自动增长,以提高性能。
StringBuffer sb= new StringBuffer(int capacity);
显式释放空间让 gc 回收对象
多数情况下,方法内部的局部引用变量所引用的对象会随着方法结束而变成垃圾被回收。因此在程序中无需将局部引用变量显式设为 null 。

示例如下:
void gcTest1() {
Object obj = new Object();
……
obj = null;
}

随着方法 gcTest1() 的执行完成,程序中局部引用变量 obj 的作用域就结束了,这时没有必要执行 obj = null 。

反例如下:
void gcTest2(){
Object obj = new Object();
……
obj = null;
//耗时,耗内存操作
……
}
此时需要尽早释放不再使用的空间,执行 obj = null 显式释放局部引用变量 obj 。

二维数组使用规范
二维数据占用的内存空间大概是一维数组的 10 倍以上。

split 使用场景
尽量避免使用 split 。split 使用正则表达式,效率比较低,如果是频繁的调用将会耗费大量资源。

如果确实需要频繁的调用 split ,使用 apache 的 StringUtils.split(string,char) 较好 ,可以缓存结果。

ArrayList 和 LinkedList 使用规范
对于线性表及链表,随机查询的操作ArrayList 优于 LinkedList ,LinkedList 需要移动指针。增加删除的操作 LinkedList 优于 ArrayList ,ArrayList 需要移动数据。

System.arraycopy() 使用规范
尽量使用 System.arraycopy() 复制数组,它要比通过循环来复制数组快的多。

缓存对象
将经常使用的对象进行缓存时,可以使用数组或者 HashMap 等容器来缓存。这种方式需要自己管理这些容器,可能导致系统占用过多的缓存,性能下降。

也可以使用一些第三方的开源工具,如 EhCache 、Oscache 进行缓存,他们基本都实现了 FIFO/FLU 等缓存算法。

尽量避免非常大的内存分配
有的问题不是由于堆内存不够造成的,而是因为内存分配失败造成的。(gc会进行内存碎片整理)

如果分配的内存块都必须是连续的,随着堆越来越满,找到较大的连续块会越来越困难。

try/catch 使用场景
不要在循环中使用 try/catch 语句,应该把 try/catch 放在循环最外层。
喜欢这样文章的可以关注我,我会持续更新,你们的关注是我更新的动力!需要更多java学习资料的也可以私信我!
祝关注我的人都:身体健康,财源广进,福如东海,寿比南山,早生贵子,从不掉发!


推荐阅读
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • Java程序设计第4周学习总结及注释应用的开发笔记
    本文由编程笔记#小编为大家整理,主要介绍了201521123087《Java程序设计》第4周学习总结相关的知识,包括注释的应用和使用类的注释与方法的注释进行注释的方法,并在Eclipse中查看。摘要内容大约为150字,提供了一定的参考价值。 ... [详细]
  • GreenDAO快速入门
    前言之前在自己做项目的时候,用到了GreenDAO数据库,其实对于数据库辅助工具库从OrmLite,到litePal再到GreenDAO,总是在不停的切换,但是没有真正去了解他们的 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 本文介绍了在Android开发中使用软引用和弱引用的应用。如果一个对象只具有软引用,那么只有在内存不够的情况下才会被回收,可以用来实现内存敏感的高速缓存;而如果一个对象只具有弱引用,不管内存是否足够,都会被垃圾回收器回收。软引用和弱引用还可以与引用队列联合使用,当被引用的对象被回收时,会将引用加入到关联的引用队列中。软引用和弱引用的根本区别在于生命周期的长短,弱引用的对象可能随时被回收,而软引用的对象只有在内存不够时才会被回收。 ... [详细]
  • 从相邻元素对还原数组的解题思路和代码
    本文介绍了从相邻元素对还原数组的解题思路和代码。思路是使用HashMap存放邻接关系,并找出起始点,然后依次取。代码使用了HashMap来存放起始点所在的adjacentPairs中的位置,并对重复的起始点进行处理。 ... [详细]
  • 本文介绍了在C#中SByte类型的GetHashCode方法,该方法用于获取当前SByte实例的HashCode。给出了该方法的语法和返回值,并提供了一个示例程序演示了该方法的使用。 ... [详细]
author-avatar
国邮国旅刘峰
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有