Java使得复杂应用的开发变得相对简单 毫无疑问 它的这种易用性对Java的大范围流行功不可没 然而 这种易用性实际上是一把双刃剑 一个设计良好的Java程序 性能表现往往不如一个同样设计良好的C++程序 在Java程序中 性能问题的大部分原因并不在于Java语言 而是在于程序本身 养成好的代码编写习惯非常重要 比如正确地 巧妙地运用java lang String类和java util Vector类 它能够显著地提高程序的性能 下面我们就来具体地分析一下这方面的问题
在江苏等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供成都网站设计、网站建设 网站设计制作定制网站建设,公司网站建设,企业网站建设,品牌网站建设,成都全网营销推广,外贸网站制作,江苏网站建设费用合理。
在java中 使用最频繁 同时也是滥用最多的一个类或许就是java lang String 它也是导致代码性能低下最主要的原因之一 请考虑下面这个例子
String s = Testing String ;String s = Concatenation Performance ;String s = s + + s ;
几乎所有的Java程序员都知道上面的代码效率不高 那么 我们应该怎么办呢?也许可以试试下面这种代码
StringBuffer s = new StringBuffer();s append( Testing String );s append( );s append( Concatenation Performance );String s = s toString();
这些代码会比第一个代码片段效率更高吗?答案是否定的 这里的代码实际上正是编译器编译第一个代码片段之后的结果 既然与使用多个独立的String对象相比 StringBuffer并没有使代码有任何效率上的提高 那为什么有那么多Java书籍批评第一种方法 推荐使用第二种方法?
第二个代码片段用到了StringBuffer类(编译器在第一个片段中也将使用StringBuffer类) 我们来分析一下StringBuffer类的默认构造函数 下面是它的代码
public StringBuffer() { this( ); }
默认构造函数预设了 个字符的缓存容量 现在我们再来看看StringBuffer类的append()方法
public synchronized StringBuffer append(String str) {if (str == null) { str = String valueOf(str); } int len = str length(); int newcount = count + len; if (newcount value length) expandCapacity(newcount); str getChars( len value count); count = newcount; return this;}
append()方法首先计算字符串追加完成后的总长度 如果这个总长度大于StringBuffer的存储能力 append()方法调用私有的expandCapacity()方法 expandCapacity()方法在每次被调用时使StringBuffer存储能力加倍 并把现有的字符数组内容复制到新的存储空间
在第二个代码片段中(以及在第一个代码片段的编译结果中) 由于字符串追加操作的最后结果是 Testing String Concatenation Performance 它有 个字符 StringBuffer的存储能力必须扩展两次 从而导致了两次代价昂贵的复制操作 因此 我们至少有一点可以做得比编译器更好 这就是分配一个初始存储容量大于或者等于 个字符的StringBuffer 如下所示
StringBuffer s = new StringBuffer( );s append( Testing String );s append( );s append( Concatenation Performance );String s = s toString();
再考虑下面这个例子
String s = ;int sum = ;for(int I= ; I ; I++) { sum += I; s = s + + +I ; }s = s + = + sum;
分析一下为何前面的代码比下面的代码效率低
StringBuffer *** = new StringBuffer();int sum = ; for(int I= ; I ; I++){ sum + = I; *** append(I) append( + ); }String s = *** append( = ) append(sum) toString();
原因就在于每个s = s + + + I操作都要创建并拆除一个StringBuffer对象以及一个String 对象 这完全是一种浪费 而在第二个例子中我们避免了这种情况
我们再来看看另外一个常用的Java类——java util Vector 简单地说 一个Vector就是一个java lang Object实例的数组 Vector与数组相似 它的元素可以通过整数形式的索引访问 但是 Vector类型的对象在创建之后 对象的大小能够根据元素的增加或者删除而扩展 缩小 请考虑下面这个向Vector加入元素的例子
Object obj = new Object();Vector v = new Vector( );for(int I= ; I ; I++) { v add( obj); }
除非有绝对充足的理由要求每次都把新元素插入到Vector的前面 否则上面的代码对性能不利 在默认构造函数中 Vector的初始存储能力是 个元素 如果新元素加入时存储能力不足 则以后存储能力每次加倍 Vector类就象StringBuffer类一样 每次扩展存储能力时 所有现有的元素都要复制到新的存储空间之中 下面的代码片段要比前面的例子快几个数量级
Object obj = new Object();Vector v = new Vector( );for(int I= ; I ; I++) { v add(obj); }
同样的规则也适用于Vector类的remove()方法 由于Vector中各个元素之间不能含有 空隙 删除除最后一个元素之外的任意其他元素都导致被删除元素之后的元素向前移动 也就是说 从Vector删除最后一个元素要比删除第一个元素 开销 低好几倍
假设要从前面的Vector删除所有元素 我们可以使用这种代码
for(int I= ; I ; I++){ v remove( ); }
但是 与下面的代码相比 前面的代码要慢几个数量级
for(int I= ; I ; I++){ v remove(v size() ); }
从Vector类型的对象v删除所有元素的最好方法是
v removeAllElements();
假设Vector类型的对象v包含字符串 Hello 考虑下面的代码 它要从这个Vector中删除 Hello 字符串
String s = Hello ; int i = v indexOf(s); if(I != ) v remove(s);
这些代码看起来没什么错误 但它同样对性能不利 在这段代码中 indexOf()方法对v进行顺序搜索寻找字符串 Hello remove(s)方法也要进行同样的顺序搜索 改进之后的版本是
String s = Hello ; int i = v indexOf(s); if(I != ) v remove(i);
这个版本中我们直接在remove()方法中给出待删除元素的精确索引位置 从而避免了第二次搜索 一个更好的版本是
String s = Hello ; v remove(s);
最后 我们再来看一个有关Vector类的代码片段
for(int I= ; Iv size(); I+=){}如果v包含 个元素 这个代码片段将调用v size()方法 次 虽然size方法是一个简单的方法 但它仍旧需要一次方法调用的开销 至少JVM需要为它配置以及清除堆栈环境 在这里 for循环内部的代码不会以任何方式修改Vector类型对象v的大小 因此上面的代码最好改写成下面这种形式
int size = v size(); for(int I= ; Isize; I++){}
lishixinzhi/Article/program/Java/gj/201311/27752
1、介绍
在开发中,性能测试是设计初期容易忽略的问题,开发人员会为了解决一个问题而“不择手段”,所参与的项目中也遇到了类似问题,字符串拼接、大量的调用和数据库访问等等都对系统的性能产生了影响,可是大家不会关心这些问题,“CPU速度在变快”,“内存在变大”,并且,“好像也没有那么慢吧”。
有很多商业的性能测试软件可供使用,如Jprofiler、JProbeProfiler等,但在开发当中显得有些遥远而又昂贵。
2、目标
本文将讲述如何利用语言本身提供的方法在开发中进行性能测试,找到系统瓶颈,进而改进设计;并且在尽量不修改测试对象的情况下进行测试。
3、预备知识
面向对象编程通过抽象继承采用模块化的来求解问题域,但是模块化不能很好的解决所有问题。有时,这些问题可能在多个模块中都出现,像日志功能,为了记录每个方法进入和离开时的信息,你不得不在每个方法里添加log("insomemethod")等信息。如何解决这类问题呢?将这些解决问题的功能点散落在多个模块中会使冗余增大,并且当很多个功能点出现在一个模块中时,代码变的很难维护。因此,AOP(AspectOrientedProgramming)应运而生。如果说OO(AobjectOrientedProgramming)关注的是一个类的垂直结构,那么AOP是从水平角度来看待问题。
动态代理类可以在运行时实现若干接口,每一个动态代理类都有一个Invocationhandler对象与之对应,这个对象实现了InvocationHandler接口,通过动态代理的接口对动态代理对象的方法调用会转而调用Invocationhandler对象的invoke方法,通过动态代理实例、方法对象和参数对象可以执行调用并返回结果。
说到AOP,大家首先会想到的是日志记录、权限和事务,是的,AOP是解决这些问题的好办法。
性能测试主要包括以下几个方面:
计算性能:可能是人们首先关心的,北大青鸟认为简单的说就是执行一段代码所用的时间
内存消耗:程序运行所占用的内存大小
启动时间:从你启动程序到程序正常运行的时间
可伸缩性(scalability)
用户察觉性能(perceivedperformance):不是程序实际运行有多快,而是用户感觉程序运行有多快.
张小喜告别996 实现高效编程 减少开发压力 开启Java高效编程之门(完整版高清视频)百度网盘
链接:
提取码: aizj 复制这段内容后打开百度网盘手机App,操作更方便哦
若资源有问题欢迎追问~
说到代码优化,每个人或多或少都掌握一到两种方法,但是这样的方法对提升代码运行效率效果不大,最重要是对代码的重视和了解,这样才能提升代码的运行效率。在进行代码优化的过程中,方法是非常重要的,多掌握几种方法,根据代码的不同情况选择适合的方法进行优化。下面电脑培训为大家介绍Java代码优化的几种方法。
1、使用指定类、方法的final修饰符
具有final修饰符的类不可派生。在Java核心API中,有许多最终应用程序的例子,例如java.lang.String,整个类都是final。为类指定final修饰符允许继承类,并且为方法指定final修饰符允许覆盖该方法。如果将类指定为final,IT培训认为该类的所有方法都是final。Java编译器将寻找内联所有最终方法的机会。内联对于提高Java操作的效率非常重要。这可以将性能平均提高50%。
2、重用对象
String对象的使用是非常重要的,StringBuilder/StringBuffer并不是字符串连接。由于Java虚拟机需要时间来生成对象,所以将来垃圾收集和处理这些对象可能需要一些时间。因此,生成太多对象将对程序的性能产生很大影响。
3、使用局部变量
调用方法时传递的参数以及在调用中创建的临时变量都保存在堆栈中,速度更快。其他变量(如静态变量和实例变量)在堆中创建并且速度较慢。此外,昆明北大青鸟发现在堆栈中创建的变量,当方法完成运行时,内容消失,不需要进行额外的垃圾收集。
4、及时关闭流
在Java编程过程中,在执行数据库连接和I/O流操作时要小心。使用后,北大青鸟云南嘉荟校区官网建议应及时关闭以释放资源。因为这些大型物体的操作会导致系统的大量开销,稍微粗心会导致严重的后果。