이펙티브 자바
아이템 6. 불필요한 객체생성을 피하라
똑같은 기능의 객체를 매번 생성하기 보다는 객체하나를 재사용하는 편이 좋을수도 있다.
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | package com.github.sejoung.codetest.objects;
 
 public class StringTest {
 public static void main(String[] args) {
 
 String string1 = "1223";
 String string2 = new String("1223");
 
 Boolean true1 = Boolean.valueOf("true");
 Boolean true2 = Boolean.valueOf("true");
 Boolean true3 = new Boolean("true");
 
 System.out.println(true1 == true2);
 System.out.println(true1 == true3);
 System.out.println(true1 == Boolean.TRUE);
 System.out.println(true3 == Boolean.TRUE);
 
 }
 }
 
 
 
 | 
결과 
| 12
 3
 4
 5
 6
 7
 
 | truefalse
 true
 false
 
 Process finished with exit code 0
 
 
 | 
위에서 보면 string을 선언 할때 생성자를 통해서 만든 1223과 기능적으로 완전히 똑같은 생성자를 통하지 않은 객체가 있다.
이것은 생성자를 통해서 만드는것은 불필요 한 일이다.
위 사항과 마찬가지로 Boolean 객체를 만들때 제공하는 Boolean.valueOf로 만든 것과 생성자를 통해서 만든것이 기능적으로는
완벽하게 똑같지만 객체는 계속 생성이 된다 이렇게 만들지 않기 위해서 정적팩토리메소드를 통해서 생성하는것을 권장한다.
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 
 | package com.github.sejoung.codetest.objects;
 
 import java.util.regex.Pattern;
 
 public class RomanNumber {
 private static final Pattern ROMAN = Pattern.compile("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
 
 static boolean isRomanNumeralCompile(String s) {
 return ROMAN.matcher(s).matches();
 }
 
 
 static boolean isRomanNumeral(String s) {
 return s.matches("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
 }
 
 public static void main(String[] args) {
 
 long start = System.currentTimeMillis();
 
 int max = 100000;
 
 for (int i = 0 ; i <= max ; i++) {
 RomanNumber.isRomanNumeral("123123");
 }
 System.out.println(System.currentTimeMillis() - start);
 
 start = System.currentTimeMillis();
 for (int i = 0 ; i <= max ; i++) {
 RomanNumber.isRomanNumeralCompile("123123");
 }
 System.out.println(System.currentTimeMillis() - start);
 
 
 
 
 }
 }
 
 
 
 
 | 
결과
| 12
 3
 4
 5
 6
 
 | 238
 18
 
 Process finished with exit code 0
 
 
 | 
isRomanNumeral 메소드도 매번 정규식을 컴파일하는것보다 위에 처럼 컴파일후에 비교하는것과는 속도 차이가 많이 난다.
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 
 | package com.github.sejoung.codetest.objects;
 
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
 public class UsingKeySet {
 
 public static void main(String[] args) {
 Map<String, Integer> menu = new HashMap<>();
 menu.put("Burger", 8);
 menu.put("Pizza", 9);
 
 Set<String> names1 = menu.keySet();
 Set<String> names2 = menu.keySet();
 System.out.println(names2.size());
 System.out.println(names1.size());
 System.out.println(menu.size());
 names1.remove("Burger");
 System.out.println(names2.size());
 System.out.println(names1.size());
 System.out.println(menu.size());
 }
 }
 
 
 
 | 
또다른 잘못된 예로 map에 keySet을 들수 있다. 위에 코드를 실행 해보면 아래의 결과가 나타난다.
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | 2
 2
 2
 1
 1
 1
 
 Process finished with exit code 0
 
 
 | 
하나의 셋을 삭제 햇는데 나머지까지 다 영향이 가는것을 볼수가 있다.
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | package com.github.sejoung.codetest.objects;
 
 public class AutoBoxingExample {
 public static void main(String[] args) {
 long start = System.currentTimeMillis();
 Long sum = 0l;
 for (long i = 0 ; i <= Integer.MAX_VALUE ; i++) {
 sum += i;
 }
 System.out.println(sum);
 System.out.println(System.currentTimeMillis() - start);
 
 start = System.currentTimeMillis();
 long sum2 = 0l;
 for (long i = 0 ; i <= Integer.MAX_VALUE ; i++) {
 sum2 += i;
 }
 System.out.println(sum2);
 System.out.println(System.currentTimeMillis() - start);
 
 }
 
 }
 
 
 | 
결과
| 12
 3
 4
 5
 6
 7
 8
 
 | 2305843008139952128
 7590
 2305843008139952128
 736
 
 Process finished with exit code 0
 
 
 | 
위에 오토 박싱에 예도 마찬 가지 이다 Long으로 선언해서 오토박싱을 하는것보다 long으로 선언해서 보면 속도차이가 많이 난다.
참조
[이팩티브 자바] #6 불필요한 객체를 만들지 말자