Egloos | Log-in


태그 : java

Java의 auto boxing과 unbox은 어떻게 컴파일될까?

  아래 코드는 프리미티브 타입과 Wrapper 클래스, 자동 Boxing, 자동 UnBoxing이라는 글에 나오는 것을 입력해 본 것입니다. int와 java.lang.Integer객체를 "=="와 "equals()"메소드로 비교하고 있습니다.

 

AutoBoxingTest.JPG 

  위의 코드에서 생성한 .class파일을 역컴파일해보면 아래와 같은 코드가 나옵니다. autoboxing과 unboxing이 어떤 방식으로 이루어 지는지 잘 확인할 수 있습니다. java.lang.Integer가 int로 바뀔 때는 intValue() 메소드, int가 java.lang.Integer로 바뀔 때는 Integer.valueOf()메소드를 사용하고 있습니다. JDK 1.4이하 버전과의 하위호환성을 위해서 이런 방식을 쓰는 것이겠죠.

 int a = 1;
 int b = 1;
 Integer c = new Integer(1);
 Integer d = new Integer(1);
 System.out.println((new StringBuilder("1:")).append(System.identityHashCode(Integer.valueOf(a))).toString());
 System.out.println((new StringBuilder("2:")).append(System.identityHashCode(Integer.valueOf(b))).toString());
 System.out.println((new StringBuilder("3:")).append(System.identityHashCode(c)).toString());
 System.out.println((new StringBuilder("4:")).append(System.identityHashCode(d)).toString());
 System.out.println((new StringBuilder("5:")).append(a == b).toString());
 System.out.println((new StringBuilder("7:")).append(c == d).toString());
 System.out.println((new StringBuilder("8:")).append(c.equals(d)).toString());
 System.out.println((new StringBuilder("9:")).append(a == c.intValue()).toString());

 

  new Integer()로 생성자를 호출하면 매로 새로 객체를 생성하는데, Integer.valueOf()메소드를 사용하면 캐쉬된 값을 사용할 수 있습니다. 이 메소드의 소스를 보면 -128부터 127까지의 static영역에 캐쉬로 쌓아두고 있습니다.

 

 static {
  cache = new Integer[256];
  for (int i = 0; i < cache.length; i++)
  cache[i] = new Integer(i - 128);
}

public static Integer valueOf(int i) {
  if (i >= -128 && i <= 127)
  return IntegerCache.cache[i + 128];
  else
  return new Integer(i);
}

 

 처음에 나왔던 저의 Eclipse 캡쳐화면을 보면 findbugs 플러그인에서 new Integer()사용 코드에 대한 경고를 보여주고 있습니다. 자세한 설명을 보니,  Integer.valueOf()를 사용할 경우 약 3.5배 정도 실행속도가 빠르다고 하네요.

M P Bx] Method invokes inefficient Number constructor; use static valueOf instead [DM_NUMBER_CTOR]

Using new Integer(int) is guaranteed to always result in a new object whereas Integer.valueOf(int) allows caching of values to be done by the compiler, class library, or JVM. Using of cached values avoids object allocation and the code will be faster.

Values between -128 and 127 are guaranteed to have corresponding cached instances and using valueOf is approximately 3.5 times faster than using constructor. For values outside the constant range the performance of both styles is the same.

Unless the class must be compatible with JVMs predating Java 1.5, use either autoboxing or the valueOf() method when creating instances of Long, Integer, Short, Character, and Byte.

 

  이런 원리들을 잘 염두해 둬서, auto boxing과 unboxing이 사용될 때 필요없는 객체가 생성되지 않는지 유의해야 합니다.

 

  다음 코드는 Effective Java 2nd Edition의 Item 5 - '불필요한 객체를 생성하지 마라'에 나오는 예제입니다.

Long sum = 0L;
for(long i=0;i< Integer.MAX_VALUE;i++){
   sum += i;
}
System.out.println(sum);

  이 코드를 컴파일한 후 다시 역컴파일 해보면 다음과 같이 나옵니다.

Long sum = Long.valueOf(0L);
for(long i = 0L; i < 0x7fffffffL; i++)  sum = Long.valueOf(sum.longValue() + i);

System.out.println(sum);

   java.lang.Double.valueOf(double) 메서드는 매번 새로운 객체를 생성하게 되어 있습니다.

public static Double valueOf(double d) {
  return new Double(d);
}

 

  이렇듯 불필요한 객체생성을 막기 위해 되도록 primitive type을 선호해야 합니다. auto boxing은 Collection이나 Map에 들어가는 요소로 변수가 쓰일 때, generics가 적용한 코드를 작성할 때 등이 적절한 사용의 예입니다. (Effective Java 2nd Edition, Item 49 참조)

by 정상혁 | 2009/02/10 08:21 | 기술 자료 | 트랙백 | 덧글(0)

Effective & Agile Java Generics

본문 내용을 인쇄하실 분은 여기를 누르시기 바랍니다.

문서정보


Generics가 들어간 테스트 코드를 통과시켜 봅시다.

  아래에 있는 테스트 1~5까지의  테스트 코드들을 모두 한번에 통과시키는 ListUtils.max메서드는 어떻게 선언하고 구현해야 할까요?

  Generics를 써보신 분이라면 ListUtilsTest.java를 다운 받으셔서 한번 풀어 보시기 바랍니다. Collections.max()를 아시는 분도 그 메소드를 참고하시지 마시고 직접 메서드를 만들어 보시면 재미있으실 겁니다. 제약조건은 다음과 같습니다.

  1. @SuppressWarnings("unchecked") 를 쓰지 않고도 Generics에 대한 warning이 없고, Casting도 한번도 하지 않아야 하고
  2. 컴파일 시점에서 ListUtils.max 메소드에 Comparable 인터페이스를 구현한 객체들을 쌓은 List가 넘어온다는 것을 검증할 수 있어야 한다.


    @Test

    public void getNullIfEmptyList(){

        List<Integer> numbers = new ArrayList<Integer>();

        Integer max = ListUtils.max(numbers);

        assertThat(max,is(nullValue()));        

    }

테스트 1 :  빈 리스트가 넘어오면 null값 반환

    @Test

    public void getMaxInteger(){

        List<Integer> numbers = new ArrayList<Integer>();

        numbers.add(Integer.valueOf(1));
        numbers.add(Integer.valueOf(2));
        Integer max = ListUtils.max(numbers);

        assertThat(max,is(Integer.valueOf(2)));

    }

테스트 2 :  Integer객체의 최대값 구하기

    @Test

    public void getMaxBigInteger(){

        List<BigInteger> numbers = new ArrayList<BigInteger>();

        numbers.add(BigInteger.ZERO);

        numbers.add(BigInteger.ONE);

        BigInteger max = ListUtils.max(numbers);

        assertThat(max,is(BigInteger.ONE));

    }

테스트 3 :  BigInteger객체의 최대값 구하기

 

    @Test
    public void getMaxDate(){
        java.sql.Date now = new java.sql.Date(new Date().getTime());
        java.sql.Date afterAWhile = new java.sql.Date(new Date().getTime()+6000);
        List<java.sql.Date> dates = new ArrayList<java.sql.Date>();
        dates.add(now);
        dates.add(afterAWhile);
        java.sql.Date max = ListUtils.max(dates);
        assertThat(max,is(afterAWhile));
    }    

테스트 4: java.sql.Date 객체의 최대값 구하기


    @Test
    public void getMaxScheduledFuture() throws InterruptedException{
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
        ScheduledFuture<?> after1Second = executor.schedule(getTask("first"),1,TimeUnit.SECONDS);
        ScheduledFuture<?> after2Seconds = executor.schedule(getTask("second"),2,TimeUnit.SECONDS);
        List<ScheduledFuture<?>> futures = new ArrayList<ScheduledFuture<?>>();
        futures.add(after1Second);
        futures.add(after2Seconds);
        ScheduledFuture<?> max = ListUtils.max(futures);
        long maxDelay = max.getDelay(TimeUnit.SECONDS);
        assertThat(maxDelay,is(after2Seconds.getDelay(TimeUnit.SECONDS)));
        Thread.sleep(3000);
        assertTrue(max.isDone());
    }
    private Runnable getTask(final String message) {
        Runnable task = new Runnable(){
            public void run() {
                System.out.println(message);
            }
        };
        return task;
    }

테스트5 : ScheduledFuture를 구현한 객체의 최대값 구하기

(java.util.concurrent.ScheduledFuture  API문서 참조)



풀이와 설명

 테스트 1,2,3번 까지의 코드만이라면 아래와 같이 선언하셔도 됩니다.

public static <T extends Comparable<T>> T max(List<T> list)

리스트 1: 간단한 max 메서드 선언

 

  이렇게 <T extends Comparable<T>> 처럼 Type parameter가 그 자신이 포함된 표현으로 그 범위가 선언되는 것을 recursive type bound라고 합니다.

  Integer와 BigDecimal의 클래스 선언을 보면 아래와 같습니다.

public final class Integer extends Number implements Comparable<Integer>

public class BigInteger extends Number implements Comparable<BigInteger>

리스트 2: Integer 와 BigInteger 클래스 선언부

 

  두 클래스 모두 자신의 타입이 Parameterized type으로 들어간 Comparable 인터페이스를 구현하고 있기 때문에 리스트3의 메소드 선언으로도 Integer나 BigInteger가 담긴 리스트를 받을 수 있습니다.


   그러나  리스트 1의 선언으로는 테스트4,5에 있는 메서드에서 컴파일 에러가 날 것입니다. 그 이유는 다음과 같습니다.

   테스트4의 java.sql.Datejava.util.Date를 상속한 클래스입니다. 그런데 java.sql.Date는 따로 comparesTo메서드를 재정의하고 있지 않고, 상위클래스인 java.util.Date에 있는 메서드를 그대로 쓰고 있습니다. 그래서 java.sql.Date는 Comparable<java.sql.Date> 한 것이 아닌 Comparable< java.util.Date> 를 구현한 것이라고 볼 수 있습니다. (두 클래스의 이름이 같아서 혼동이 되실 수도 있습니다. Java Puzzler에서는 이 두 클래스의 예를 들면서 자바 플랫폼 설계자가 이름을 지으면서 깜빡 존 듯하다고 언급하고 있습니다.)

  그리고 테스트5의 java.util.concurrent.ScheduledFuture 인터페이스는 Comparable<ScheduledFuture>를 구현한 것이 아닌, Delayed라는 인터페이스를 상속한 것이고, 이 Delayed는 Comparable<Delayed>를 상속한 인터페이스입니다.  l리스트 3의 인터페이스 선언을 보시면 쉽게 이해가 되실 것입니다.

public interface ScheduledFuture<V> extends Delayed, Future<V>

public interface Delayed extends Comparable<Delayed>

리스트 3: ScheduledFutureDelayed 인터페이스 선언부

 

  이런 경우도 모두 통과할 수 있게 ListUtils.max()메서드를 선언하고 구현하면 아래와 같습니다.

public class ListUtils {
    public static <T extends Comparable<? super T>> T max(List<T> list){
        T result = null;
        for(T each : list) {
            if (result==null) result = each;
            if(each.compareTo(result)>0) result = each;
        }
        return result;
    }
}

리스트4: ListUtils 구현(다운로드: ListUtils.java

 

  public static <T extends Comparable<? super T>> T max(List<T> list) 라는 긴 메서드 선언입니다. 이 선언 안에는 recursive type bound, wild card, upper bound, lower bound가  다 들어가 있습니다. 이 정도 메서드를 설계할 수 있어야지, Java generics를 제대로 아는 것이라고 할 수 있겠습니다.

   bounded wild card를 적용하는 기준은 Effective Java 2nd Edition에 나와 있는 PECS(Producer-extends, Consumer-super)원칙을 기억하시면 도움이 됩니다. 원래 PECS의 뜻은 가슴 근육이라는군요.


<T extends Comparable.... 부분

  Comparable인터페이스를 구현한 클래스가 그 대상이어야 max내부에서 Comparable.compareTo를 이용해서 최대값을 구할 수 있습니다. 그래서 타입 T는 T extends Comparable이 되어야 합니다. PECS원칙으로도 리턴값으로 생산되는 (Producer) 타입이 T이므로 extends를 쉽게 연상하실 수 있습니다.

Comparable<? super T> 부분

   max 메서드 내부에서 타입 T는 Comparable.compareTo(T o)메서드 뒤에 파라미터로 넘어가는, 소비되는(Consumer) 대상으로 쓰이기에 PECS원칙으로 super로 연결시킬 수 있습니다. 테스트5의 코드를 예로 보면, ScheduledFuture는 ScheduledFuture의 상위 인터페이스인 Delayed가 Comparable의 Parameterized type으로 넘어가는 Comparable<Delayed>형태의 Comparable인터페이스를 상속하고 있습니다.  T를 ScheduledFuture로 봤을 때 Comparable<? super T>는 Comparable<Delayed>와 잘 맞아떨어집니다.

  이 리스트4의 ListUtils.max 메서드는 Effective Java 2nd Edition의 Item28에 나오는 코드를 보고서 약간 변경을 해 본 것입니다. 원래 책에 나오는 코드는 아래와 같습니다.


public static <T extends Comparable<? super T>> T max(List<? extends T> list){
  Iterator<? extends T> i = list.iterator();
  T result = i.next();
  while(i.hasNext()){
            T t = i.next();
            if (t.compareTo(result)>0) result = t;
   }
   return result;
}

리스트5: Effective Java 2nd Edition에 있는 max메서드

 

  메서드 선언이 public static <T extends Comparable<? super T>> T max(List<? extends T> list)로 예제보다 더 늘어난 부분이 있습니다. 끝에 있는 List<? extends T>가 추가된 것입니다. 이 부분은 PECS원칙에 따르면 List객체로부터 T를 생산(Producer)해 오기 때문에 ? extends T로 하는 것이 적절해 보이는 합니다. 그러나 테스트1~5의 코드에서는 List<T>만으로도 컴파일러가 수행하는 형추론(type inference)에 문제가 없었기에 제가 만든 코드인 리스트4에는 추가하지는 않았습니다. 컴파일러가 수행하는 Type inference는 굉장히 복잡하고, Java Language Spec에서 16페이지나 차지한다고 합니다.

  그리고, 리스트5에서는 길이가 0인 List가 넘어간 값일 때는 첫번째 i.next();에서 NoSuchElementException을 내게 되어 있습니다.

java.util.Collections.max메 서드에서도 같은 결과가 나오는 것으로 보아서, 유사한 구현방식이 쓰인 것으로 추측됩니다. 제가 만든 문제에서는 Collection.max와 약간 다른 부분을 만들어 보고 싶어서 길이가 0일 list가 올 때는 null을 반환하는 방식으로 바꾸어 보았습니다.

  그렇다면 java.util.Collections.max의 메서드 시그니처는 어떻게 되어 있을까요?


static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)

리스트6: java.util.Collections.max 메서드

  일단 대상이 List보다 확장된 Collection이니 Parameter가 Collection인 것이 눈에 들어 옵니다. 그런데 T의 제약조건이 <T extends Object & Comparable<? super T>>로 선언되어 있는 것이 리스트5의 코드보다 'Object &' 부분이 더 들어가 있습니다.

  이것은 java1.4와의 하위 호환성을 위한 것입니다. Java에서는 하위호환성 지원 때문에 컴파일 시에 Generics관련 정보를 모두 검사한 후에는 실제로는 Generics 정보가 전혀 없는 바이트코드를 생성하게 되어 있습니다. 그래서 리스트5처럼 메서드를 선언했을 때에는 런타임시에는 리스트 7과 같은 코드와 같은 바이트코드가 생성됩니다.

static Comparable max(Collection c)

리스트 7: 리스트5의 메서드 선언이 자료형 지우기가 수행된 뒤의 모습

 

그러나 이전 버전에서의 max메서드의 모습은 다음과 같았습니다.

public static Object max(Collection c)

리스트8: Java5 이전의 Collections.max 메서드

 

 따 라서 리스트7처럼 Comparable을 반환하게 된다면 이것은 이전버전의 메서드 Signature를 바꿔버린 것이 되므로 하위버전에서 컴파일된 코드에서 Collections.max를 호출할 때 에러를 발생시키게 됩니다. 그래서 Object &이 더 추가된 것이죠. (Agile Java의 Lesson 12 중 Additional Bounds에서 참조)

  여기까지 이해하셨으면, 실무에서 어떤 Generics 관련 코드를 봐도 이제 쉬워보이실 겁니다.

Generics의 표현력

   하나의 예제로 Generics의 많은 부분을 설명하기 위해서 다소 복잡한 코드를 보여드렸습니다. 혹시나 Generics를 이제 막 적용하시고 싶으신 분들의 마음을 어둡게 한 것이 아닌가 걱정이 되기도합니다. 그러나 대부분의 Generics적용 사례는 훨씬 간단하고, 특히 Collection 선언에 genercics를 활용하는 정도는 어렵지 않습니다.

  Generics는 컴파일시점에서의 에러검출 영역을 넓혀줘서 보다 이른 시점에 버그를 잡을 수 있게 해주고, 코드I의 설명력을 높여줘서 API사용자들이 보다 쉽게 API를 쓸 수 있게 해줍니다. 컴파일타입의 에러체크 능력은 위의 예제를 통해서 설명했으니, 표현력에 대해서도 제가 겪은 사례를 이야기해 볼까 합니다.

  몇년전에 저는 Java 인터페이스를 엑셀파일로 만드는 산출물 작업을 하고 있었는데, 리턴타입이 List인 메서드들은 그 안에 어떤 객체들이 들어있는지 메서드 시그니처만으로는 표현할 수 없어서 답답했던 적이 있었습니다. 그래서 아예 List대신 배열을 쓸까도 고민하다가 List가 가진 편의성들을 버릴 수가 없어서 List를 쓰고 따로 문서에 그 안에 어떤 객체가 들어가 있는지를 적을 수 밖에 없었습니다.

  javax.servlet.ServletRequest.getParameterMap()를 사용할 때는 API사용자로서 아쉬움을 느꼈었습니다. API문서를 보면 이 메서드가 반환하는 Map에는 key로 String이, value로 String배열이 들어가 있는 것으로 설명되어 있습니다.


getParametersMap.GIF

 저 는 처음에 이 문서를 안 보고 key가 String, 값이 하나일 때는 그냥 String, 값이 2개 이상이면 String배열이 들어가 있지 않을까하는 추측을 바탕으로 한 코드를 짜서 몇번 에러를 냈었었습니다. 결국 API문서를 보고서 어떤 형식으로 자료가 들어가 있는지 알게 되어있습니다. 이 메소드의 리턴타입이 Map<String,String[]>과 같이 선언되어 있었다면, 문서를 안 보고도, Runtime 에러를 안 겪고도 바로 올바른 자료형으로 사용이 가능했을 것입니다. 나중에 저는 이 메서드를 호출하는 부분을 아래와 같이 감싸는 부분을 넣었습니다.


@SuppressWarnings("unchecked")
Map<String,String[]> requestMap = request.getParameterMap();

리스트9:  javax.servlet.ServletRequest.getParameterMap() 메서드를 Generics를 이용한 코드로 감싸기

 

  @SuppressWarnings("unchecked")은 어쩔 수 없는 경우에만 써야 하고, 쓸 때도 클래스 단위, 메서드 단위가 아닌 이런 최소 라인 단위로 써야 합니다. (Effective Java 2nd Edition Item 24참조) 이 경우는 Generics지원하지 않는 외부 인터페이스를 호출하는 것이라서 불가피한 경우이고, 형에 대해서는 API 문서에 명시된 내용라서 이렇게 @SuppressWarnings을 선언해도 문제가 없습니다. 필요에 따라서 이 requestMap을 리턴해 준다면 그것을 쓰는 코드에서는 더 이상 이 안에 무엇이 들어있는지 문서를 찾아보지 않아도 됩니다.

  이렇듯 Generics를 잘 활용해보면 이것이 괜히 코드를 복잡하게 만드는 것이 아니고, API설계자와 사용자들에게 많은 도움이 된다는 것을 느끼실 것입니다.


  Sun에서는 공식적으로 JDK1.4의 서비스 기간의 종료를 선언했다고 합니다. 이 시기에 현장에서 Generics를 활용할 줄 아는 Java 개발자의 수는 많이 부족해 보입니다.


관련자료 모음

Generics 관련자료

이 포스트는 주로 아래 두 책을 보면서 얻은 정보를 통해 작성되었습니다.

  Agile java처럼 테스트 코드를 먼저 보여주었고 , ListUtils.max 메서드는 Effective Java의 내용을 주로 참조해서 작성했습니다. Effective Java에서는 ScheduledFuture의 경우에 대해서 언급만 되어 있고 예제코드가 없는 것이 아쉬워서 테스트5의 코드를 작성했고, 비슷한 사례의 보다 친숙한 클래스를 찾다가  Agile java에서 java.sql.Date 클래스가 예제에 많이 쓰인 것을 보고 테스트4를 추가했습니다.


Effective Java 2nd Edition 에 포함된 내용 중 Java5 관련 내용은 Joshua Bloch이 했던 발표에 잘 요약되어 있습니다.

그외 Generics에 관한 자료들의 링크는 아래와 같습니다.


테스트 코드 작성 관련자료

혹시나 위에 쓰인 Junit4 방식의 Test annotation이나 assertThat 메소드가 익숙하시지 않으신 분들은 아래 자료를 참고하시기 바랍니다.


그 리고 Eclipse를 사용해서 Junit4를 사용할 때 가장 귀찮은 점인 Ctrl+Shift+O를 누르면 static import의 *까지도 다 펼쳐지는 현상은 아래와 자료를 참고하셔서 Eclipse 설정을 바꾸시면 좀 더 편하시게 코딩하실 수 있습니다.


Concurrent 관련자료

Effective Java에서 언급한 ScheduledFuture를 이용한 예제코드를 만들다 보니 Concurrent관련 API들이 몇개 포함되었습니다. 그 API들에 관심이 있으신 분은 아래 자료를 참조하시면 됩니다.


List<ScheduledFuture<?>>의 코드가 실전에서 쓰인 것이 없을까해서 찾아보니 반갑게도 Spring 포트폴리오의 일부분인 Spring integration에 있는 소스 코드에서 그런 코드가 발견되었습니다.



by 정상혁 | 2008/12/16 22:03 | 기술 자료 | 트랙백 | 덧글(11)

Java에서 Checked Exception은 언제 써야 하는가?

  Java 의 Exception 처리는 C++에서 도입되었지만 checked exception은 Java만의 독특한 특징입니다. 아시다시비, 컴파일러가 exception을 꼭 처리해라고 강요하는 것이죠.  이것은  java 이후에 설계된 언어인 C#이나 루비에도 채택되지 않았습니다. 즉 Java 이외의 다른 언어들의 Exception 처리 방식은 Java의 unchecked exception과 동일한 방식입니다.

  Java의 초기에 checked Exception의 사용을 권장하던 것에 대해서 지금은 많은 반론이 제기되고 있습니다. 극단적으로 Java언어의 Checked Exception 도입 자체가 실패라고 주장하는 사람도 많습니다. Thinking in Java의 저자인 Bruce Eckel도 그 중 한 사람입니다.  Spring framework의 아버지 Rod Johnson도 Checked Exception이 쓰여야 할 때도 있지만 그 것이 과도하게 선호되어 온 것은 지적하고 있습니다.

  어쨓든 Exception 부분은 Java로 API 설계와 코딩를 할 때 가장 어려운 부분이라고 느껴집니다. Java 아키텍트와 개발팀의 실력을 측정하는 좋은 방법은 그들이 만든 Exception 처리 코드를 보라는 말까지 있으니까요.

 

 Exception 처리 방식 참고자료

 

  • Expert One-on-One J2EE Design and Development 중 Chapter 4 Design Techniques and Coding Standards for J2EE Projects, Exception Handling 부분

    • alternative return value가 있는 경우에는 Checked exception
    • data connection 생성 실패와 같이 뭔가 크게 잘못 되고 있어서 호출한 쪽에서 아무도 이를 처리할 수 없을 때는 Runtime exception.
    • 소수의 호출자만이 Exception을 받아서 처리해야 할 때도 Runtime exception.
    • 불명확하면 Runtime exception.
    • checked Exception과 Runtime exception 페이지에서 일부 내용이 번역되어 있습니다.
    • Spring 프레임웍크 워크북 (박재성 저) 88쪽에도 인용되어 있는 원칙입니다.

 

  • Barry Ruzek의  EFFECTIVE JAVA EXCEPTIONS

    • Fault Handling(Unplanned condition)에는 RuntimeException, Contingency(Expected condition, alternative method result)에는 return type, exception, error code 등의 전략을 사용
    • Fault를 한곳에서 잡아서 처리하는 Fault barrier pattern 사용 권장. Struts라면 org.apache.struts.action.ExceptionHandler, SpringMVC라면 SimpleMappingExceptionResolver
    • AOP 적용이 도움이 될 수도 있음.
    • 황상철님의 블로그 Effective Java Exceptions 발표자료 페이지에서 이 내용이 요약된 pdf 파일을 받을 수 있습니다. (effective java exceptions.pdf )

 

 

 

  • Gunjan Doshi의 Best Practices for Exception Handling

    • Client code가 할 일이 있을 때는 checked, 없을 때는 unchecked. progamming error에는 unchecked exception.
    • 적절한 캡슐화. 비지니스 layer에서 SqlException을 던지지 말것.

 

 

  • Alan Griffiths의 Exceptional Java

    • 이 주제에 대해 비교적 초기에 나온 글로써, 다른 글에도 많이 인용되고 있습니다.
    • Exception 처리에 대한 전통적인 원칙이 캡슐화 저해, 정보손실, 정보 과적의 문제를 일으킨다고 이야기합니다.
    • public 메소드에서 던지는 Exception은 해당 패키지에 소속된 클래스일것, 다른 패키지에서는 이를 부를 때를 Exception을 전파시키지 말고 그 패키지의 Exception으로 감쌀 것을 추천하고 있습니다.

 

 

Checked Exception에 대한 부정적 견해를 정리한 글

  • Brian Goetz의 글: Java theory and practice: The exceptions debate

    • Bruce Eckel, Rod Johnson, Joshua Bloch등의 주장을 정리해 놓은 글입니다. Checked Exception이 상세한 구현을 부적절하게 노출함,불안정한 메소드 시그너처,읽기힘든 코드,Exception 삼키기,너무 많은 Exception wrapping의 문제점 있는 것을 나열하고 있습니다. unchecked exception은 Documentation이 더욱 중요하다고 강조하고 있습니다.

 

  • Rod Waldhoff의 글 : Java's checked exceptions were a mistake

    • Java의 Exception Handling은 실패한 실험이라고 주장하는 내용입니다. Checked Exception방식은 일부 low level에서만 의미가 있다고 말합니다.

 

  • Bruce Eckel의 견해(Thinking in Java의 저자): Does Java need Checked Exceptions?

    • Error report 방식을 통일했다는 점에서는 의미가 있지만, 오히려 개발자들이 Exception을 그냥 삼키는 코드를 많이 짜게 하는 결과가 생겼다고 지적합니다.

 

  • Bill Venners(C#의 아키텍트)와 Bruce Eckel의 인터뷰 : The Trouble with Checked Exceptions

    • versioning, scalability의 문제 때문에 C#에  Checked Exception이 도입되지 않았다고 밝히고 있습니다.


Checked Exception에 대한 논의가 진행된 페이지

 

이클립스 Exception처리 코드 템플릿 관련 자료

by 정상혁 | 2008/05/23 07:58 | 기술 자료 | 트랙백(5) | 핑백(1) | 덧글(0)

◀ 이전 페이지          다음 페이지 ▶