1. 合理使用final
将Java局部变量定义为final有多重好处,包括提高代码可读性、防止变量被意外修改、优化性能、避免多线程安全问题和满足语法规范。
- 提高代码可读性:使用final修饰局部变量可以明确表达变量的含义和作用,使得代码更加易读易懂,从而提高代码的可读性。
- 防止变量被意外修改:final修饰的局部变量在程序的其他地方不会被无意中修改,这有助于防止在程序执行过程中对变量的值进行不期望的更改,从而提高了代码的可维护性。
- 优化性能:使用final修饰局部变量可以帮助编译器进行优化,从而提高程序的执行效率。这是因为编译器可以针对final变量进行一些特定的优化,因为知道这些变量的值在使用过程中不会被修改。
- 避免多线程安全问题:在多线程环境下,final修饰的局部变量是线程安全的,因为它们的值一旦被赋值就不会改变。这避免了在多线程环境中可能出现的并发问题。
- 满足语法规范:在某些情况下,如lambda表达式中,Java编译器要求局部变量必须使用final修饰符。因此,将局部变量定义为final也是满足语法规范的一种方式。
2. 避免过度封装
java 代码编写过度封装的危害
在Java中,过度的封装可能会导致一些潜在的问题,如增加了系统的复杂性、可能降低了系统的性能、可能降低了代码的可读性和可维护性。
以下是一些过度封装可能导致的问题的例子:
-
增加了系统的复杂性:每次访问对象的属性时,都需要通过getter和setter方法,这可能会使代码变得冗长复杂。
-
可能降低了系统的性能:在Java中,访问对象的私有属性需要通过getter和setter方法,这可能会导致一定的性能损失。
-
可能降低了代码的可读性和可维护性:过度的封装可能会使代码难以理解,特别是对于那些不熟悉封装细节的开发者。
解决方案:
-
适度封装:在保证代码可读性和可维护性的前提下,适当的封装是必要的。
-
使用public final字段:对于不应该被外部修改的字段,可以使用public final修饰,这样外部只能读取,不能修改。
-
使用Lombok库:Lombok是一个Java库,它可以自动生成getter、setter等方法,减少了代码的冗余。
综上所述,不要刻意要求代码的封装,一般一个业务一个方法,尽量不要超过200行就可以了,对于写业务逻辑的程序员来说,没有必要刻意封装。
3.避免在循环中创建大量对象
在Java中,在循环中创建大量对象可能导致内存溢出问题,因为这会占用大量的堆内存。如果对象创建过于频繁,可能会导致垃圾回收器(GC)频繁运行,这将影响应用程序的性能并降低整体吞吐量。
解决方案通常包括:
-
优化代码以减少对象创建的次数。
-
使用对象池或其他缓存机制来复用对象。
-
如果必须在循环中创建大量临时对象,请确保及时地让对象变成垃圾以便被GC回收。
// 优化实践:创建对象之前先初始化
MyObject obj = null;
for (int i = 0; i < 10000; i++) {
if (obj == null) {
obj = new MyObject();
}
}
// 最后如果obj还在使用范围内,确保释放对象以避免内存泄漏
obj = null;
// 更优化的实践:使用对象池
ObjectPool<MyObject> pool = new ObjectPool<>(MyObject::new);
for (int i = 0; i < 10000; i++) {
MyObject obj = pool.borrowObject();
// 使用obj...
pool.returnObject(obj); // 对象使用完毕后归还到池中
}
4.尽量避免重复调用值固定的方法(方法的调用是有额为的性能损耗的)
如下:
for(int i = 0; i < list.size() ; i ++)
//在每次遍历时都要调用list.size() 应改为
for(int i = 0, len = list.size() ; i < len ; i ++)
5.直接访问成员变量和访问get/set方法到底哪个更好
直接访问对象的成员通常比通过方法调用对象的成员更快。
在Java中,访问对象的成员变量或调用对象的方法有几种不同的方式,每种方式都有其特定的性能特点。根据提供的数据,我们可以得出以下结论:
-
直接访问对象的成员变量(属性访问)通常比通过getter/setter方法访问要快。这是因为直接访问避免了方法调用的开销。根据提供的数据,getter/setter的性能已经接近直接属性访问,大约慢50%,这意味着在大多数情况下,没有必要担心getter/setter的性能而采用直接属性访问。
-
使用Map来存储和访问对象属性比使用getter/setter方法要慢得多,大约慢三倍。这表明,在考虑性能时,直接访问对象的成员变量或使用getter/setter方法通常是更优的选择。
-
反射访问,无论是通过Field还是通过Method访问,都比直接访问或使用getter/setter方法慢得多,甚至可以达到150倍的差异。反射访问的代价不仅在于性能上,还在于它增加了代码的复杂性,因此应谨慎使用。
-
JIT(Just-In-Time编译器)的作用:在重复次数增加的情况下,方法访问和属性访问的差距缩小。有趣的是,反射的Method访问比Field访问快四倍。这主要是JIT的作用,它能够优化重复执行的代码,提高其执行效率。
综上所述,直接访问对象的成员变量通常比通过方法调用对象的成员更快。在选择访问方式时,应考虑到性能、代码的可读性和维护性等因素。在大多数情况下,使用getter/setter方法已经足够满足性能需求,并且提供了更好的封装性。而在需要动态性和灵活性时,可以考虑使用反射,但需要权衡其带来的性能开销