>Java >java지도 시간 >35가지 Java 코드 성능 최적화 방법 공유

35가지 Java 코드 성능 최적화 방법 공유

怪我咯
怪我咯원래의
2017-04-05 15:58:401654검색

머리말

코드 최적화는 매우 중요한 주제입니다. 어떤 사람들은 그것이 쓸모없다고 생각할 수도 있습니다. 수정할 수 있는 작은 것들은 무엇입니까? 수정이 코드의 실행 효율성에 어떤 영향을 미치나요? 저는 이런 질문에 대해 이렇게 생각합니다. 바다의 고래처럼 작은 새우를 먹는 것이 도움이 될까요? 소용없었는데 새우를 더 먹다보니 고래가 배불러요. 코드 최적화도 마찬가지입니다. 프로젝트가 최대한 빨리 버그 없이 출시하는 데 중점을 둔다면 이때는 큰 것에 집중하고 작은 것을 버릴 수 있으며, 코드의 세부 사항을 다듬을 필요가 없습니다. ; 하지만 코드를 개발하고 유지 관리할 시간이 충분하다면 이때는 모든 측면을 고려해야 합니다. 최적화할 수 있는 세부 사항이 하나씩 쌓이면 코드의 실행 효율성이 확실히 향상됩니다.

코드 최적화의 목표는 다음과 같습니다.

1. 코드 크기 줄이기

2. 코드 실행 효율성 향상

코드 최적화 세부정보

1. 클래스와 메소드의 최종 수식어를 지정해 보세요.

최종 수식어가 있는 클래스는 파생될 수 없습니다. Java 핵심 API에는 전체 클래스가 최종인 java.lang.String과 같은 최종 애플리케이션의 예가 많이 있습니다. 클래스에 final 수정자를 지정하면 클래스가 상속되지 않으며, 메서드에 final 수정자를 지정하면 메서드가 재정의되지 않습니다. 클래스가 final로 지정되면 해당 클래스의 모든 메서드가 final이 됩니다. Java 컴파일러는 모든 최종 메소드를 인라인할 수 있는 기회를 찾습니다. 인라인은 Java 실행 효율성을 향상시키는 데 중요한 역할을 합니다. 이를 통해 성능을 평균 50% 향상할 수 있습니다.

2. 객체 재사용을 시도하세요

특히 문자열 연결이 발생할 경우 StringBuilder/StringBuffer를 대신 사용해야 합니다. JVM(Java Virtual Machine)은 객체를 생성하는 데 시간을 소비할 뿐만 아니라 향후 이러한 객체를 가비지 수집하고 처리하는 데에도 시간을 소비해야 할 수 있습니다. 따라서 너무 많은 객체를 생성하면 프로그램 성능에 큰 영향을 미칩니다.

3. 로컬 변수를 최대한 사용하세요

메소드 호출 시 전달된 매개 변수와 호출 중에 생성된 임시 변수는 정적 변수 등 기타 변수에 더 빨리 저장됩니다. 인스턴스 변수 등은 모두 힙에 생성되므로 속도가 느려집니다. 또한 메소드가 종료되면 스택에 생성된 변수의 내용은 사라지므로 추가 가비지 수집이 필요하지 않습니다.

4. 적시에 스트림을 닫습니다.

Java 프로그래밍 프로세스 중에 데이터베이스 연결 및 I/O 스트림 작업을 수행할 때 주의하여 릴리스할 시간에 스트림을 닫습니다. 자원. 이러한 대형 개체에 대한 작업은 많은 시스템 오버헤드를 유발하므로 조금만 부주의해도 심각한 결과를 초래할 수 있습니다.

5. 변수의 반복 계산 최소화

메서드에 명령문이 하나만 있어도 스택 프레임을 생성하고 호출할 때를 포함하여 메서드를 호출하면 비용이 많이 듭니다. 메소드 장면을 보호하고, 메소드 호출 시 장면을 복원합니다. 따라서 예를 들어

for (int i = 0; i 48c28b1a8266ebd241424beac87f32a3重写了Object的toString()方法。<h3>31、不要对超出范围的基本数据类型做向下强制转型</h3><p>这绝不会得到想要的结果:</p><pre class="brush:java;toolbar:false;">public static void main(String[] args){ 
    long l = 12345678901234L;
    int i = (int)l;
    System.out.println(i);
}

我们可能期望得到其中的某几位,但是结果却是:

1942892530

解释一下。Java中long是8个字节64位的,所以12345678901234在计算机中的表示应该是:

0000 0000 0000 0000 0000 1011 0011 1010 0111 0011 1100 1110 0010 1111 1111 0010

一个int型数据是4个字节32位的,从低位取出上面这串二进制数据的前32位是:

0111 0011 1100 1110 0010 1111 1111 0010

这串二进制表示为十进制1942892530,所以就是我们上面的控制台上输出的内容。从这个例子上还能顺便得到两个结论:

1、整型默认的数据类型是int,long l = 12345678901234L,这个数字已经超出了int的范围了,所以最后有一个L,表示这是一个long型数。顺便,浮点型的默认类型是double,所以定义float的时候要写成”"float f = 3.5f”

2、接下来再写一句”int ii = l + i;”会报错,因为long + int是一个long,不能赋值给int

32、公用的集合类中不使用的数据一定要及时remove掉

如果一个集合类是公用的(也就是说不是方法里面的属性),那么这个集合里面的元素是不会自动释放的,因为始终有引用指向它们。所以,如果公用集合里面的某些数据不使用而不去remove掉它们,那么将会造成这个公用集合不断增大,使得系统有内存泄露的隐患。

33、把一个基本数据类型转为字符串,基本数据类型.toString()是最快的方式、String.valueOf(数据)次之、数据+”"最慢

把一个基本数据类型转为一般有三种方式,我有一个Integer型数据i,可以使用i.toString()、String.valueOf(i)、i+”"三种方式,三种方式的效率如何,看一个测试:

public static void main(String[] args){ 
    int loopTime = 50000;
    Integer i = 0; 
    long startTime = System.currentTimeMillis(); 
    for (int j = 0; j < loopTime; j++){
        String str = String.valueOf(i);
    }

    System.out.println("String.valueOf():" +
     (System.currentTimeMillis() - startTime) + "ms");
    startTime = System.currentTimeMillis(); 
     for (int j = 0; j < loopTime; j++){
        String str = i.toString();
    }

    System.out.println("Integer.toString():" +
      (System.currentTimeMillis() - startTime) + "ms");
    startTime = System.currentTimeMillis(); 
      for (int j = 0; j < loopTime; j++){
    
    String str = i + "";
    
    }

    System.out.println("i + \"\":" + 
      (System.currentTimeMillis() - startTime) + "ms");

}

运行结果为:

String.valueOf():11ms Integer.toString():5ms i + "":25ms

所以以后遇到把一个基本数据类型转为String的时候,优先考虑使用toString()方法。至于为什么,很简单:

1、String.valueOf()方法底层调用了Integer.toString()方法,但是会在调用前做空判断

2、Integer.toString()方法就不说了,直接调用了

3、i + “”底层使用了StringBuilder实现,先用append方法拼接,再用toString()方法获取字符串

三者对比下来,明显是2最快、1次之、3最慢

34、使用最有效率的方式去遍历Map

遍历Map的方式有很多,通常场景下我们需要的是遍历Map中的Key和Value,那么推荐使用的、效率最高的方式是:

public static void main(String[] args){
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("111", "222");
Set<Map.Entry<String, String>> entrySet = hm.entrySet();
Iterator<Map.Entry<String, String>> iter = entrySet.iterator();
while (iter.hasNext()){
    Map.Entry<String, String> entry = iter.next();
    System.out.println(entry.getKey() 
    + "\t" + entry.getValue());
}
}

如果你只是想遍历一下这个Map的key值,那用”Setf7e83be87db5cd2d9a8a0b8117b38cd4 keySet = hm.keySet();”会比较合适一些

35、对资源的close()建议分开操作

意思是,比如我有这么一段代码:

try{
    XXX.close();
    YYY.close();
}catch (Exception e){
...
}

建议修改为:

try{
     XXX.close();
}catch (Exception e) {
     ... 
}
try{
  YYY.close();
}catch (Exception e) {
    ...
}

虽然有些麻烦,却能避免资源泄露。我们想,如果没有修改过的代码,万一XXX.close()抛异常了,那么就进入了cath块中了,YYY.close()不会执行,YYY这块资源就不会回收了,一直占用

위 내용은 35가지 Java 코드 성능 최적화 방법 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.