'java'에 해당되는 글 21건

  1. throw new UnsupportedOperationException() (4) 2009/10/30
  2. [Effective Java] 23. 새로 작성하는 코드에서는 원천(raw) 타입을 사용하지 말자. 2009/10/30
  3. [Effective Java] 19. 타입을 정의할 때만 인터페이스를 사용하자. (2) 2009/10/27
  4. [Effective Java] 15. 가변성을 최소화하자. (2) 2009/10/19
  5. [Effective Java] 11. clone 메소드는 신중하게 오버라이드 하자. (2) 2009/10/15
  6. [Effective Java] 9. equals 메소드를 오버라이드 할 땐 hashCode 메소드도 항상 오버라이드 하자. 2009/09/28
  7. [Effective Java] 8. equals 메소드를 오버라이딩 할 때는 보편적 계약을 따르자. (3) 2009/09/24
  8. [Effective Java] 5. 불필요한 객체 생성을 피하자 (4) 2009/09/23
  9. [Effective Java] 4. private 생성자를 사용해서 인스턴스 생성을 못하게 하자 2009/09/17
  10. Eclipse Galileo에 어떤 프로젝트가 있을까? (2) 2009/08/26
  11. [Effective Java] 3. private 생성자나 enum 타입을 사용해서 싱글톤의 특성을 유지하자. (3) 2009/08/26
  12. [Effective Java] 생성자의 매개변수가 많을 때는 빌더(builder)를 고려하자. (3) 2009/07/31
  13. [dW] Ajax와 자바 개발을 간단하게 시리즈~ (4) 2008/09/23
  14. [dW] REST 서비스 작성하기 (2) 2008/06/30
  15. [dW] Practically Groovy: Reduce code noise with Groovy 2008/06/24
  16. [dW] XStream으로 자바 객체를 XML로 직렬화하기 (6) 2008/05/22
  17. [dW] 동적인 언어를 동적으로 호출하기, Part 1: 자바 스크립팅 API (한글) (2) 2008/04/30
  18. [dW] 클래스 로딩 문제 분석하기 (4) 2008/03/04
  19. Derby에서 paging구현.. (7) 2007/09/03
  20. awt와 swing의 차이점 (6) 2007/06/19

throw new UnsupportedOperationException()

Posted at 2009/10/30 10:23// Posted in 나만의 작업/Java

자동생성되는 메소드에 throw new UnsupportedOperationException()넣기

 
이클립스에서 제공해주는 코드 템플릿을 이용하여, 인터페이스를 만들고 그 구현체를 퀵픽스를 통해 메소드를
자동생성했을 때 리턴값이 있을 경우 컴파일에러가 일시적으로 나지 않게 해주기 위해서 return null; 이나 
return 0; 이나 임시땜빵으로 이런작업을 해주는데 이게 귀찮을 때

throw new UnsupportedOperationException()을 코드 템플릿을 이용하여 넣어주는 방법

이클립스라면 Preference – Java – Code Style – Code Templates 안에 Code/Method Body에 이를 추가해주면 된다.


자꾸 까먹어서, 링크 해 둡니다.
  1. 2009/10/31 00:25 [Edit/Del] [Reply]
    음.. 내 경우도 자꾸 까먹어서 링크하거나 글로 남겨두곤 하니.. ㅎㅎㅎ

    이클립스.. 오랫만에 본다+_+

    잘 지내고 있지? 환절기 감기 조심하구~ (신종플루보다 독감이 더 무서워...^^)

    행복한 11월 맞이하렴~
  2. [NC]...YellOw
    2009/11/01 22:00 [Edit/Del] [Reply]
    행복한 11월 맞이하세요~

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret


[Effective Java] 23. 새로 작성하는 코드에서는 원천(raw) 타입을 사용하지 말자.
 
제네릭을 사용하면 각 컬렉션에 어떤 타입의 객체를 허용할 것인지 컴파일러에게 알려주게 되며, 캐스트 코드를 컴파일러가 자동으로 만들어준다. 또한 잘못된 타입의 객체를 추가하려고 하면 컴파일 시에 알려준다.
 
하나 이상의 타입 매개변수(type parameter)를 선언하고 있는 클래스나 인터페이스를 제네릭 클래스, 또는 제네릭 인터페이스라고 한다.
자바 1.5를 기준으로 List 인터페이스에는 하나의 타입 매개변수로 E가 있는데, 여기서 E는 List에 저장되는 요소의 타입을 나타낸다.
 

각 제네릭 타입에서는 원천(raw) 타입을 정의하는데 원천 타입이란 실 타입 매개변수가 없이 사용되는 제네릭 타입의 이름을 말한다.
예를 들어, List<E>에 대한 원천 타입은 List로써, 마치 타입 선언에서 제네릭 타입 정보가 지워진 것처럼 동작하는데, 실제로는 제네릭이 추가되기 전에 인터페이스 타입 List가 했던 것과 같은 방법으로 동작한다.
 
앞으로 작성하는 새 코드에 List와 같은 원천 타입을 사용하면 안 되지만, List<Object>처럼 어떤 객체도 List에 추가 할 수 있는 매개변수화 타입은 사용해도 좋다. 그렇다면, 원천 타입인 List와 매개변수화 타입인 List<Object>의 차이는 무엇일까? 전자는 제네릭 타입의 검사가 생략되는 반면, 후자는 어떤 타입의 객체도 저장할 수 있다는 것을 컴파일러에게 명시적으로 알려주려는 것이다. 따라서 List<String> 타입은 List의 매개변수로 전달할 수 있지만,  List<Object>의 매개변수로는 전달할 수 없다. 제네릭에는 서브 타입 규칙이 있어서 List<String>은 원천 타입인 List의 서브타입이지만 매개변수 타입인 List<Object>의 서브타입은 아니다.
그런이유로, List와 같은 원천 타입을 사용하면 타입의 안전성을 상실하게 되지만, List<Object>과 같은 매개변수 타입을 사용하면 그렇지 않다.
 
타입 안전의 대안으로 언바운드 와일드 카드(unbound wildcard type)을 제공하고 있다. 제네릭 타입은 사용하고 싶지만 실 타입 매개변수를 모르거나, 어떤 타입이든 관계없다면 타입 대신 물음표(?)를 사용하면 된다. 예를 들어 제네릭 타입 Set<E>의 언바운드 와일드 카드 타입은 Set<?>.
이것은 어떤 타입의 객체(Set포함)도 저장할 수 있는 가장 보편화된 매개변수화 Set 타입이다.
 
언바운드 와일드 카드 타입인 Set<?>과 원천 타입인 Set의 차이는 무엇일까? 와일드 카드 타입은 안전하고 원천 타입은 그렇지 않다.
원천 타입의 컬렉션에는 어떤 타입의 요소도 추가할 수 있지만, 해당 컬렉션의 타입불변성을 쉽게 무너뜨릴 수 있다.
 
향후에 작성하는 새 코드에는 원천 타입을 사용하지 않는다는 규칙에도 두 가지 예외가 있는데, 런타임 시에는 제네릭 타입의 정보가 없어진다는 것 때문에 가능하다.
첫번째로, 원천 타입은 클래스 리터럴(class literal)의 형태로 사용해야 한다. List.class, String[].class, int.class는 모두 적법하지만, List<String>.class, List<?>.class는 허용되지 않는다.
두번째로, instanceof 연산자와 관련. 제네리 타입의 정보는 런타임시에 없어지므로 언바운드 와일드 카드 타입이 아닌 다른 매개변수화 타입에 대해 instanceof 연산자를 사용할 수 없다. 원천 타입 대신 언바운드 와일드 카드 타입을 사용할 때는 instanceof 연산자의 동작에 영향을 주지 않으며, 이 경우 <>와 물음표(?)는 아무 의미가 없다. 제네릭 타입과 함께 instanceof 연산자를 사용할 때는 다음과 같이..
 
// Legitimate use of raw type - instanceof operator
if (o instanceof Set) { // Raw type
Set<?> m = (Set<?>) o; // Wildcard type
...
}
 
o가 Set타입이라는 것이 결정되면, o의 타입을 원천타입(Set)이 아닌 언바운드 와일드 카드 타입(Set<?>)으로 캐스팅해야 한다. 그리고 이런 캐스팅은 타입을 확인하고 하는 것이므로 컴파일 시 경고 메시지가 나오지 않을 것이다.


댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret


[Effective Java] 19. 타입을 정의할 때만 인터페이스를 사용하자.
 

 // Constant interface antipattern - do not use!
public interface PhysicalConstants {
// Avogadro's number (1/mol)
static final double AVOGADROS_NUMBER = 6.02214199e23;
// Boltzmann constant (J/K)
static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
// Mass of the electron (kg)
static final double ELECTRON_MASS = 9.10938188e-31;
}
 
상수 인터페이스 패턴은 인터페이스를 형편없이 사용한다. 향후 배포판에서 그 상수를 더 이상 사용할 필요가 없어서 클래스를 변경하더라도 바이너리 호환성을 유지하기 위해 여전히 그 상수 인터펭스를 구현해야 한다.
 
상수를 외부에 제공하고 싶을 때 적절한 방법

만일 어떤 상수가 기존 클래스나 인터페이스와 밀접하게 연관된다면, 그 상수를 해당 클래스나 인터페이스에 추가해야 한다.
예. Integer나 Double과 같은 모든 박스화 기본형 클래스에서는 MIN_VALUE와 MAX_VALUE 상수를 외부에 제공한다.
만일 상수가 열거타입(enumerated type)의 멤버가 되는 것이 가장 좋다면 enum타입으로 한다.
그렇지 않으면, 인스턴스를 생성할 수 없는 유틸리티 클래스에 상수를 두어야 한다.
 
//상수 유틸리티 클래스
package com.effectivejava.science;
public class PhysicalConstants {
private PhysicalConstants() { } // Prevents instantiation
public static final double AVOGADROS_NUMBER = 6.02214199e23;
public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
public static final double ELECTRON_MASS = 9.10938188e-31;
}
 
유틸리티 클래스의 경우, 클라이언트가 상수를 사용할 때 상수 명 앞에 그 유틸리티 클래스 명을 붙여야 한다. PhysicalConstants.BOLTZMANN_CONSTANT 와 같이.
만일 유틸리티 클래스의 상수를 무척 많이 사용한다면, static import문을 사용해서 상수 명 앞에 클래스 명을 붙이지 않게 하면 된다.
이렇게..
 
import static com.effectivejava.science.PhysicalConstants.*;
public class Test {
double atoms(double mols) {
return AVOGADROS_NUMBER * mols;
}
...
// Many more uses of PhysicalConstants justify static import
}
 
결론, 인터페이스는 타입을 정의할 때만 사용해야 한다. 상수를 외부에 제공하기 위해 사용하면 안된다.


  1. [NC]...YellOw
    2009/10/28 21:34 [Edit/Del] [Reply]
    오늘도 열공하시는군여.. 화이팅~
    근데 언제 쏘는건가요? ㅋ

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret


[Effective Java] 15. 가변성을 최소화하자.

불변(immutable) 클래스는 자신의 인스턴스가 갖는 값을 변경할 수 없는 클래스이다. 각 인스턴스가 갖는 모든 정보는 그것이 생성될 때 제공되며 객체로 살아있는동안 변경되지 않는다. 자바의 불변 클래스는 String, 박스화 기본형(boxed primitive) 클래스, BigInteger, BigDecimal 등등이 있다.
불변 클래스는 가변 클래스에 비해 설계와 구현 및 사용이 더 쉽다. 또한 에러 발생이 적으며 보안이나 사용 측변에서 더 안전하다.
 
불변 클래스 만들때 다섯 가지 규칙

1) 객체의 상태를 변경하는 그 어떤 메소드(변경자라고 하는)도 제공하지 않는다.

2) 상속을 할 수 없도록 하자. 일반적으로는 클래스를 final로 지정하면 상속을 막을 수 있다.

3) 모든 필드를 final로 지정한다. 새로 생성된 불변 클래스 인스턴스의 참조가 스레드간의 동기화를 하지 않고 하나의 스레드에서
다른 스레드로 확실하게 전달되도록 하는데도 필요하다.

4) 모든 필드를 private으로 지정한다. 필드로 참조되는 가변 객체를 클라이언트가 직접 접근하여 객체의 내용을 변경하는 것을 막기위함이다. 불변 클래스의 public final필드에서 기본형 데이터 값이나 불변 객체의 참조를 갖는 것이 기술적으로는 가능하다. 그러나 향후에 그 클래스의 내부 구조를 변경하기 어렵기 때문에 바람직하지 않다.

5) 가변 컴포넌트의 직접적인 외부 접근을 막자. 만일 가변 객체를 참조하는 필드가 클래스에 있다면, 그 클래스의 클라이언트가 해당 가변 객체의 참조를 획득할 수 없게 하자. 즉, 클라이언트가 주는 객체 참조로 그런 필드를 초기화해서는 절대 안되며, 접근자 메소드에서 객체 참조를 반환해도 안된다. 그대신 생성자와 접근자 메소드 및 readObject메소드에서 해당 객체의 방어 복사본(defensive copy)을 만들어 사용하도록 하자.


  1. [NC]...YellOw
    2009/10/20 14:15 [Edit/Del] [Reply]
    구구절절 옳은 말인거 같네요. ^.~

    곧 겨울이 오려나봐요. 날씨가 점점.. 흑..

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret

[Effective Java] 11. clone 메소드는 신중하게 오버라이드 하자.


Cloneable 인터페이스는 복제를 허용하는 객체라는 것을 알리는 목적으로 사용하는 믹스인 인터페이스(mixin interface)

아무런 method도 없는 Cloneable 인터페이스는 어디에 쓰이는 것일까?

이 인터페이스는 Object 클래스의 protected 메소드인 clone의 행동 방식을 규정한다. 만약, clone 메소드가 호출된 객체가 Cloneable 타입이라면, Object.clone 메소드는 이 객체의 모든 필드를 그대로 복사한 복제본을 리턴한다. 하지만 Cloneable 타입이 아니라면 CloneNotSupportedException을 던진다.

java.lang.Object.clone의 명세(Specification)

this 객체의 복제본을 생성하여 리턴한다. "복제본"의 정확한 의미는 this 객체의 클래스마다 달라질 수 있다. 

보통 모든 객체 x에 대하여, 다음 식
x.clone() != x
는 true 이고, 또 다음 식
x.clone().getClass() == x.getClass()

도 true이지만 반드시 지켜야 할 사항은 아니다. 또 다음 식

x.clone().equals(x)

도 true이지만 반드시 지켜야 할 사항은 아니다. 어떤 객체를 복제할 때 보통 이 객체 클래스의 새로운 인스턴스는 반드시 생성해야 하지만, 내부 데이터 구조도 역시 복제해야 할지도 모른다. 이 메소드는 어떤 생성자도 호출하면 안 된다.


만일 어떤 클래스로부터 상속받는 서브 클래스를 만들고 그 서브 클래스에서 super.clone을 호출하면, 서브 클래스의 인스턴트가 복제되어 반환될거라고 생각할 것이다.
이 경우 슈퍼 클래스에서 그렇게 할 수 있는 유일한 방법은, 자신의 clone 메소드에서 super.clone을 호출하여 얻은 객체를 반환하는 것이다.

만일, 슈퍼 클래스의 clone 메소드에서 또 다시 super.clone을 호출하지 않고 생성자를 호출하여 생성된 객체를 반환한다면 잘못된 클래스(타입)의 객체가 될 것이다.

그러므로 final이 아닌 수퍼 클래스의 clone 메소드를 오버라이드 할 경우, 서브 클래스의 clone에서 반드시 super.clone을 호출하여 얻은 객체를 반환해야 한다.



일반적인 Class의 clone() method
- field가 모두 기본형 타입일 경우

public Object clone() {
        try {
                return super.clone();
        } catch(CloneNotSupportedException e) {
                throw new Error("Assertion failuer");
        }
}



어떤 객체가 가변 객체를 참조하는 필드를 갖고 있는 Stack클래스를 생각해 보자.

Stack 클래스의 clone 메소드가 올바르게 동작하려면, 원본 객체가 내부적으로 포함하고 있는 객체까지도 복제해주어야 한다.

그리고 그렇게 하는 가장 쉬운 방법은, elements 배열에 대해 재귀적으로 clone 메소드를 호출하는 것이다.

Cloneable을 implements 하는 클래스의 서브 클래스에서는 clone 메소드를 잘 구현해야한다.

객체를 복제하는 다른 방법을 제공하거나, 또는 복제할 수 없도록 하는 것이 좋다.

예를 들어, 불변 클래스의 객체 복제를 지원하는 것은 바람직하지 않다. 사실상 복제본이 원본과 같기 때문이다.


객체를 복제하는 좋은 방법은 복제 생성자나 복제 팩토리 메소드를 제공하는 것이다. 복제 생성자는 그냥 생성자로써, 그 생성자를 포함하는 클래스를 타입으로 하는

인자를 하나만 갖는다. 


public Yum(Yum yum);


복제 팩토리는 복제 생성자와 유사한 static 팩토리 메소드로 다음과 같다.


public static Yum newInstance(Yum yum);


복제 생성자와 복제 팩토리 메소드를 사용하는 방법은 Cloneable 과 Clone을 사용하는 것에 대해 많은 장점을 갖고 있다.


  1. [NC]...YellOw
    2009/10/16 16:20 [Edit/Del] [Reply]
    오버라이드에 맛들이셨군요.

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret

9. equals 메소드를 오버라이드 할 땐 hashCode 메소드도 항상 오버라이드 하자. 

Java API Object.hashCode 메소드 spec에 명시

- 애플리케이션 실행 중에 같은 객체에 대해 한 번 이상 호출되더라도 hashCode 메소드는 같은 정수를 일관성있게 반환해야 한다.

- equals(Object) 메소드 호출 결과 두 객체가 동일하다면, 두 객체 각각에 대해 hashCode 메소드를 호출했을 때 같은 정수 값이 나와야 한다.

- equals(Object) 메소드 호출 결과 두 객체가 다르다고 해서 두 객체 각각에 대해 hashCode 메소드를 호출했을 때 반드시 다른 정수 값이 나올 필요는 없다.
그러나 같지 않은 객체들에 대해 hashCode 메소드에서 서로 다른 정수 값을 반환하면, 이 메소드를 사용하는 해시 컬렉션(HashMap, HashSet, Hashtable)의
성능을 향상시킬 수 있음을 알아야 한다.

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret

8. equals 메소드를 오버라이딩 할 때는 보편적 계약을 따르자.


equals메소드를 오버라이드 하지 않고 써야할때
- 클래스의 각 인스턴스가 본래부터 유일한 경우
- 두 인스턴스가 논리적으로 같은지 검사하지 않아도 되는 클래스의 경우
- 수퍼 클래스에서 equals를 이미 오버라이딩 했고, 그 메소드를 그대로 사용해도 좋은 경우
- private나 패키지 전용 클래스라서 이 클래스의 equals 메소드가 절대 호출되지 않아야 할 경우

그럼 언제 해야하나?

객체 참조만으로 인스턴스의 동일 여부를 판단하는 것이 아니라, 인스턴스가 갖는 값을 비교하여 논리적으로 같은지 판단할 필요가 있는 클래스로써,
자신의 수퍼클래스에서 equals 메소드를 오버라이드하지 않았을 때다. 일반적으로 값(value) 클래스가 해당된다.
객체의 참조 여부보다 객체가 갖는 값이 논리적으로 같은지가 관심사일때, 또한 Map의 키나 Set의 요소로 객체를 저장하고 사용할 수 있게 하려면 equals 메소드의
오버라이딩이 꼭 필요하다. 같은 객체가 이미 있는지 비교하는 수단을 제공해야 하기 때문이다.

equals 메소드를 오버라이드 할 필요 없는 값 클래스는 각 값 당 최대 하나의 객체만 존재하도록 인스턴스 제어를 사용하는 클래스
열거형이 그런 부류에 속하는데 그런 클래스들의 경우는 논리적인 일치와 객체 참조 일치가 동일한 의미가 된다.

equals 메소드를 만드는 방법

1) 객체의 값을 비교할 필요 없고 참조만으로 같은 객체인지 비교 가능하다면 == 연산자를 사용하자. 

2) instanceof 연산자를 사용해서 전달된 인자가 올바른 타입인지 확인하자.

대개의 경우 올바른 타입이란 호출된 equals 메소드가 정의된 클래스를 말하지만, 그 클래스가 구현하는 인터페이스도 올바른 타입이 될 수 있다. 
따라서 어떤 인터페이스를 구현하는 클래스들이 여러 개 있고, 각 클래스들은 equals 계약에 맞게 equals 메소드를 오버라이딩 하고 있다면, 
그 인터페이스 타입으로 각 클래스들의 객체를 비교할 수 있다. 예를 들어 Set, List, Map, Map.Entry 같은 컬렉션 인터페이스가 그런 형태이다.

3) 인자 타입을 올바른 타입으로 변환한다. 이러한 타입 변환은 instanceof 검사 후에 행하게 되므로 예외가 생기지 않고 안전하게 처리된다.

4) 클래스의 "중요한(꼭 비교해야 하는)" 필드 각각에 대해서는 인자로 전달된 객체의 필드와 현재 객체(equals 메소드가 호출된)의 필드가 모두 같은지 빠뜨리지 말고 비교한다.

5) equals 메소드가 대칭적이며 이행적이며 일관성이 있는지 확인한다.
대칭적(Symmetric) : y.equals(x) 가 true이면, x.equals(y)도 true 여야한다.
이행적(Transitive) : x.equals(y) 가 true이면, y.equals(z)가 true이면 x.equals(z)도 true
일관성(Consistent) : x.equals(y)를 여러번 호출해도 일관성있게 값을 리턴해야한다.


유의점.
equals 메소드를 오버라이드 할 땐 hashCode 메소드도 항상 오버라이드 한다.
너무 지나치게 동일 여부를 비교하려는건 좀... 동일 파일을 참조하는  심볼릭 링크 객체들이 같은지 File 클래스의 equals 에서 비교하려고 하면 안 된다.
equals 메소드의 인자 타입을 Object 대신 다른 타입으로 바꾸지 말자.



  1. 2009/09/24 11:46 [Edit/Del] [Reply]
    오.. 나도 이책 있는데 책 안읽고 요기 정리올라오는거 읽어야겠다 ㅋ

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret

5. 불필요한 객체 생성을 피하자

불변(immutable) 객체는 항상 재사용가능하다.

String s = new String("buri"); 

이렇게 쓰지 말고

String s = "buri"; 

이렇게 쓰자는거

실행될 때마다 새로운 인스턴스를 생성하지 않고 하나의 String 인스턴스를 사용하며 같은 JVM에서 실행되는 어떤 코드에서도 동일한 문자열 리터럴(literal)을 갖도록 재사용될 것이다.

불변 클래스의 불필요한 객체 생성을 막으려면 생성자보다는 static 팩토리 메소드를 사용하는 것이 좋다.
생성자인 Boolean(String)보다는 static 팩토리 메소드인 Boolean.valueOf(String)을 사용하는 것이 더 좋다.
생성자는 호출될 때마다 새 객체를 만드는 반면, static 팩토리 메소드는 결코 그럴 필요가 없고 실제로 그렇게 하지도 않는다.

  1. 2009/09/24 11:18 [Edit/Del] [Reply]
    흠... String s = "abc" 해도
    결국 new String('a', 'b', 'c') 하는 거니까...
    객체 생성 한다는 측면에선 별 차이가 없는...

    문제가 되는 건 new String(antoherString)하는 과정에서 불필요한 메모리 복사가 발생한다는... 정도...^^
    • 2009/09/28 13:28 [Edit/Del]
      ^^ 자주 등장하는 String 객체생성.
      말씀해주셨다시피 String s = "abc"도 결국 내부적으론 new String 을 하는거니 성능상의 문제는 비슷하죠.
      불필요한 작업을 피하자는 것~ ^^
  2. [NC]...YellOw
    2009/09/28 09:17 [Edit/Del] [Reply]
    호~ 역시 멋지군요. 언제 한번 스타 한판 떠요~

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret

4. private 생성자를 사용해서 인스턴스 생성을 못하게 하자
static 메소드나 static 필드만을 모아 놓은 클래스를 만들필요가 있는 유틸리티성 클래스는 인스턴스 생성이 무의미하다. 
그러나 그런 클래스라도 명시적으로 지정한 생성자가 없을때 컴파일러가 디폴트 생성자 (public 이며 매개변수가 없는)를 만들어주기 때문에 javadoc 프로그램으로 생성하는 API 문서에도 나타나기 때문에 인스턴스 생성이 가능한 클래스로 오인될 수 있다.

생성자 호출을 통한 인스턴스 생성을 방지하고 API 문서에도 나타나지 않도록 하려면?

private 생성자를 정의하면 인스턴스 생성이 불가능한 클래스를 만들 수 있다.

public class UtilityClass {
//이 클래스는 인스턴스 생성이 불가능하다라는 주석을 다는게 좋겠다.
private UtilityClass(){
throw new AssertionError(
}
}

명시적으로 정의한 생성자가 private 이므로 클래스 외부에서는 생성자 호출이 불가능하고 AssertionError는 이 생성자가 클래스 내부에서 우연히 호출될 경우를 대비.

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret

Eclipse Galileo가 릴리즈 된지 좀 되었다.
릴리즈가 되어 업데이트 할 때마다 어떤 프로젝트가 들어있는지 관심있게 살펴보지 않았는데, 
이렇게  다양한 프로젝트들이 있구나.. 
dW에 있는 아티클을 보고 한번 알고 가는게 좋을 듯 하다. 

Eclipse Galileo 살펴보기

최신 버전의 오픈 소스 다목적 IDE 및 애플리케이션 플랫폼의 새로운 기능


표 1. Galileo 릴리스 트레인 프로젝트

프로젝트 개요 웹 사이트
ACTF(Accessibility Tools Framework) 장애가 있는 사용자를 위한 애플리케이션 및 컨텐츠 개발 http://www.eclipse.org/actf/
BIRT(Business Intelligence and Reporting Tools) 보고서 생성 http://www.eclipse.org/birt
CDT(C/C++ Development Tooling) C/C++ 코드 작성 http://www.eclipse.org/cdt
DTP(Data Tools Platform) 확장 가능한 프레임워크 및 도구 http://www.eclipse.org/datatools/
EMF(Eclipse Modeling Framework) 모델링 프레임워크 및 코드 생성 기능 http://www.eclipse.org/modeling/emf/
Eclipse Packaging Project 패키지 작성, 다운로드 및 설치 http://www.eclipse.org/epp/
Eclipse Platform 핵심 프레임워크 및 서비스 http://www.eclipse.org/platform/
Equinox OSGi R4 핵심 프레임워크 스펙의 구현 http://www.eclipse.org/equinox/
GEF(Graphical Editor Framework) 그래픽 애플리케이션 개발 http://www.eclipse.org/gef/
GMF(Graphical Modeling Framework) 그래픽 편집기 개발 http://www.eclipse.org/gmf/
JWT(Java™ Workflow Tooling) 설계부터 모니터링까지의 워크플로우 및 프로세스를 위한 도구 세트 http://www.eclipse.org/jwt/
JDT(Java Development Tools) Java 애플리케이션 개발 http://www.eclipse.org/jdt/
M2T JET(Java Emitter Templates) 모델을 기반으로 텍스트 아티팩트 생성 http://www.eclipse.org/modeling/m2t/
Memory Analyzer 메모리 누수 진단 및 메모리 사용량 절감 http://www.eclipse.org/mat/
MTJ(Mobile Tools for Java) 모바일 장치용 Java 애플리케이션 개발을 위한 Eclipse 프레임워크 확장 http://www.eclipse.org/dsdp/mtj/
Mylyn 수행 중인 작업을 모니터링하여 작업에 적합한 GUI 만들기 http://www.eclipse.org/mylyn/
PDT(PHP Development Tools) PHP 코드 작성 http://www.eclipse.org/pdt/
RAP(Rich Ajax Platform) Ajax 코드 작성 http://www.eclipse.org/rap/
SCA Tools SCA(Service Component Architecture) 표준을 위한 도구 http://www.eclipse.org/stp/sca/
SOA Tools SOA(Service-Oriented Architecture) 애플리케이션 코드 작성 http://www.eclipse.org/stp/
Swordfish 확장 가능한 SOA 프레임워크 http://www.eclipse.org/swordfish/
Target Management 원격 시스템 구성 및 관리 http://www.eclipse.org/dsdp/tm/
TPTP(Test and Performance Tools Platform Project) 프로파일링 및 테스트 애플리케이션을 위한 도구 http://www.eclipse.org/tptp/
Textual Modeling Framework(Xtext) 외부 텍스트 DSL 코드 작성 http://www.eclipse.org/modeling/tmf/
TmL(Tools for mobile Linux) 모바일 애플리케이션 코드 작성 http://www.eclipse.org/dsdp/tml/
WTP(Web Tools Platform) 웹 및 Java EE 애플리케이션 코드 작성 http://www.eclipse.org/webtools/

  1. [NC]...YellOw
    2009/08/31 10:46 [Edit/Del] [Reply]
    호.. 이거 유용한데요. 잘 쓸게요 ^^;

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret

3. private 생성자나 enum 타입을 사용해서 싱글톤의 특성을 유지하자.
싱글톤(singleton)은 정확히 하나의 인스턴스만 생성되는 클래스. 싱글톤은 본질적으로 유일한 시스템 컴포넌트를 나타낸다.

예를 들면, 윈도우 매니저나 파일 시스템 등

자바 1.5 이후 싱글톤 구현하는 가장 좋은 방법

//열거형( Enum) 싱글톤
public enum Elvis {
      INSTANCE;
      public void leaveTheBuilding() { ... } 
}

복잡한 직렬화나 리플렉션 상황에서도 직렬화가 자동으로 지원되고, 인스턴스가 여러 개 생기지 않도록 확실하게 보장해준다.
  1. 2009/08/30 17:07 [Edit/Del] [Reply]
    오... enum 으로 싱글턴을... 신기하네요~
    INSTANCE; 구문도 첨 본거고...

    자바도 아직 공부할 게 많이 남았네요 ^^;;
    • 버리
      2009/09/01 12:17 [Edit/Del]
      Heart님 올만이에요~^^
      저도 이번에 effective java 2nd 책 보면서 싱글턴으로 하는거 알아서..^^
      메소드에 접근하고 싶다면,
      Elvis.INSTACE.leaveTheBuilding();
      이렇게 접근하면 된답니다.^^
  2. 2011/12/14 10:37 [Edit/Del] [Reply]
    오호~ enum 내부에 메소드나, 타입이 없는 필드도 들어가나 보군요~

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret

Static 팩토리 메소드와 생성자의 공통적인 제약은 선택 가능한 매개변수가 많아질 경우 신축성 있게 처리하지 못한다는 것인데, 흔히 나도 그러한데 텔리스코핑 생성자(telescoping constructor)패턴을 사용한다. 
필수 매개변수들만 갖는 생성자, 필수 매개변수들과 선택 매개변수 하나를 갖는 생성자, 선택 매개변수 두개를 갖는 생성자 등등의 형태로 오버로딩을 통해 여러개의 생성자를 겹겹이 만드는 것이다.

public class User{
    private String id;
    private String pw;
    private String address;
    // .......15 more field

    public User(String id, String pw){
         this(id, pw, null);
    }
    
    public User(String id, String pw, String address){
        this(id,pw,address);
    }
     //..... more constructor
}

이런식으로 필요한 매개변수만큼의 생성자를 만드는 방법.
매개변수가 몇개 안된다면 문제가 그리 되지 않지만 많으면 많을수록 가독성도 떨어지고 생성자를 찾아가고 또 찾아가고는 하다보면 실수를 유발할 수도 있다.

그럼 자바빈즈(JavaBeans)패턴 사용은 어떨까?

Class에 Setter method를 만들고, 
User user = new User();
user.setId("id");
user.setPw("pw");
user.setAddress("address");
...//more setter method

코드는 길어지지만 인스턴스 생성이 간단하고 코드의 가독성도 좋다..
하지만, 단점은 불변(immutable) 클래스를 만들 수 있는 가능성을 배제하고 스레드(thread)에서 안정성을 유지하려면 다른 작업이 필요하다. 

그럼 조금 더 우아한 방법은? Builder pattern!

public class NutritionFacts {
    public class Builder {
        public Builder(String name, int servingSize,  int servingsPerContainer) { ... }
        public Builder totalFat(int val) { ... }
        public Builder saturatedFat(int val) { ... }
        public Builder transFat(int val) { ... }
        public Builder cholesterol(int val) { ... }
        ... // 15 more setters

        public NutritionFacts build() {
                   return new NutritionFacts(this);
       }
    }
    private NutritionFacts(Builder builder) { ... } 
    }
}

이렇게 선언을 해놓고
NutritionFacts twoLiterDietCoke = new NutritionFacts.Builder("Diet Coke", 240, 8).sodium(1).build();

Builder의 setter method는 연속적으로 여러 번 호출될 수 있도록 빌더 자신의 객체를 반환한다.
코드 작성도 쉽고 가독성도 좋다!!!! 
생성자처럼 빌더는 자신의 매개변수에 불변규칙(invariants : 매개 변수나 필드가 가질 수 있는 값의 약속된 범위나 타입 및 형태를 말한다.)을 적용할 수 있고 build method는 불변 규칙을 검사할 수 있다. 
매개변수들의 값이 빌더로부터 객체에 복사된 후 빌더의 필드가 아닌 객체의 필드에 대해 불변 규칙 검사를 수행된다.

또 다른 장점은 여러개의 가변인자(varargs) 매개변수를 가질 수 있고, 유연성이 좋다. 

단점은, 어떤 객체를 생성하려면 우선 그것의 빌더를 생성해야 하기 때문에 빌더 객체의 생성 비용이 많이는 아니지만 성능이 매우 중요한 상황에서는 문제가 될 수 있다. 

결론은 생성자나 static 팩토리 메소드에서 많은 매개변수를 갖게 될 클래스를 설계할 때 빌더 패턴이 좋다는거~~위의 두 패턴보다 가독성도 좋고 자바빈즈 패턴보다 안전하다는 거~~


참고 
Effective Java 2nd book

Effective Java Reloaded : http://developers.sun.com/learning/javaoneonline/2006/coreplatform/TS-1512.pdf?






  1. [NC]...YellOw
    2009/08/06 13:42 [Edit/Del] [Reply]
    오~ 이런.. 무슨말인지 한개도 모르겠네요 -0-
  2. sebah
    2010/08/03 15:21 [Edit/Del] [Reply]
    좋은 책이죠. 저도 잘 보고 있습니다. 한가지.. public class Builder -> public static class Builder 로 변경해야 겠죠? ^^

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret


dW에서 3주동안 시리즈로 올라오는 글 중 웹개발에 도움되는 글이 있군요.

Ajax와 자바 개발을 간단하게, Part 1
JSP 태그 파일로 자바스크립트 코드 동적으로 생성하기 내용인데
HTML과 URL 인코딩 함수 - 유틸리티 함수가 유용하군요~

Ajax와 자바 개발을 간단하게, Part 2
JSTL과 JSP 태그 파일을 사용하여 커스터마이징이 가능한 웹 컴포넌트를 만들기

Ajax와 자바 개발을 간단하게, Part 3
자바스크립트와 JSP 태그 파일을 사용하여 사용자 친화적이고 웹 폼에 안전한 검증 기능을 구현하기

사용자가 웹 브라우저에 입력한 값을 자바스크립트로 검사하는 valid 같은 특정 기능에 얽매이지 않고 더 일반적인  함수를 만들 수 있는 코드가 있군요.
저같이 수련이 많이 필요한 사람에겐~  배울게 많군요...
  1. seattle
    2008/09/23 20:17 [Edit/Del] [Reply]
    블로그에 한동안 소식이 없어서 궁금했었는데, 역시 열공중이었군요! 멋져부려요~
    • 2008/09/24 10:31 [Edit/Del]
      열공은... 매일 마음속 다짐으로^^
      늘 변함없이 들러주시는 seattle님이 더 멋진데요!ㅋㅋ
      잘 계시죠?ㅎㅎ 여기서 안부묻기..ㅎㅎ
  2. 2008/09/24 00:34 [Edit/Del] [Reply]
    오랜만에 들려봅니다 :)
    AJAX라... 일단 내용은 패스;;
    한결같은 열공이 멋지네요 ㅎㅎ

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret

[dW] REST 서비스 작성하기

Posted at 2008/06/30 23:38// Posted in 나만의 작업/dW
REST 서비스 작성하기

이 글은 REST(Representation State Transfer)와 Atom Publishing Protocol(APP)에 관한 개념이 잘 나와있습니다. 그리고 REST/APP 기반의 서비스 구현 방법도 예로 나와있지요~


본문 내용중에,

REST 원칙은 URI(Uniform Resource Identifiers)를 사용하여 주어진 자원 표현의 위치를 알아내고 접근한다. 표현 상태(representational state)라 알려진 자원 표현은 만들어질 수도, 찾아올 수도, 수정될 수도, 삭제될 수도 있다. 예를 들어 REST를 적용하여 문서를 발행해 독자들이 이 문서를 읽을 수 있게 할 수 있다. 언제든 문서를 발행할 때는 웹 URL을 보여줘야 한다. 그래야 독자들이 그 문서의 정보(표현 상태)에 접근할 수 있다. 문서를 읽는 사람은 URL만 알면 문서 정보를 읽을 수 있고 승인이 있다면 정보를 수정할 수 있다.

HTTP 기반 REST 시스템에서는 GET, PUT, POST, DELETE라는 표준 HTTP 메서드를 사용하여 자원의 표현 상태에 접근해야 한다.

APP는 REST 개념과 기술을 사용하여 의미적으로 풍부한 콘텐츠 교환에 쓰이는 여러 메커니즘을 정형화기 위해 인기있는 아톰 배급 포맷(Atom Syndication Format) 위에 구축된다.
  • GET: 컬렉션이나 멤버 자원 표현을 찾아오는 데 쓰인다.
  • POST: 새 멤버 자원을 만드는 데 쓰인다.
  • PUT: 멤버 자원을 갱신하는 데 쓰인다.
  • DELETE: 멤버 자원을 삭제하는 데 쓰인다.
HTTP 프로토콜을 거쳐 자원을 전달하는 시스템에 REST 원칙을 적용하는 데 자바 프로그래밍 언어를 사용할 수 있다. APP를 사용하여 이런 시스템을 확장하고 블로그 엔트리, 포드캐스트, 위키 페이지, 달력 엔트리 등을 사용하여 자원 접근 및 조작을 용이하게 할 수 있다.

Tag APP, dw, java, REST
  1. seattle
    2008/07/01 07:44 [Edit/Del] [Reply]
    우왕~ 블로깅에 다시 발동 거셨군요. 하지만 알아볼 수 있는 내용이 아니라는거 ㅠㅠ

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret

요즘 Groovy에 대해 조금 공부하고 있는데 dW에 찾아보니 Groovy에 특성이 나타나 있는 글을
발견했는데 자바에서의 noise와 복잡성을 Groovy를 사용해서 제거하는 방법이 주로 나타나있습니다.


자바에서 JavaBean을 썼을때와 Groovy에서 Bean을 생성했을때의 코드차이.
Groovy에서도 Junit을 이용해 테스트 코드를 작성하는 법, polymorphism, Spring framework를 사용하는 방법들이 소개되어 있습니다.

Groovy에 대해 직접적인 언급보다는 기존 자바코드와 비교해서 또는 자바와 함께 쓸때의 장점등이 나타나있군요.
이래서 Groovy를 쓰면 편하겠다~ 라는 글.. ^^

Practically Groovy: Reduce code noise with Groovy


Tag dw, Groovy, ibm, java

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret

자바객체를 직렬화하려면 흔히 어떻게 하는 방법이 있을까요?
오픈 소스 라이브러리를 써주는 센스!를 발휘하려면 어떤 라이브러리가 있는지 알아야겠지요.
전 dW에 번역글이 올라와서 알게 된 XStream이 있는데 정말 몇줄로 자바객체를 XML로 직렬화 시켜주는 군요.

[dW] XStream으로 자바 객체를 XML로 직렬화하기

이곳을 참조하면, 이클립스 프로젝트에서 클래스를 생성해서 단 몇줄로 자바객체를 XML로 직렬화하는 방법이 나와있습니다. 친절하게 이클립스의 스크린샷까지..

XStream 사이트에 가보면 제일 첫 화면에 보이는

"XStream" is a simple library to serialize objects to XML and back again.

정말 심플한 라이브러리일까? 한번 소스를 봐보면..

Person joe = new Person("Joe", "Walnes");
joe.setPhone(new PhoneNumber(123, "1234-456"));
joe.setFax(new PhoneNumber(123, "9999-999"));
String xml = xstream.toXML(joe);


이렇게 대략 프로그래밍을 하면 XML결과는..(물론 Person 객체가 존재해야겠지요)

<person>
<firstname>Joe</firstname>
<lastname>Walnes</lastname>
<phone>
<code>123</code>
<number>1234-456</number>
</phone>
<fax>
<code>123</code>
<number>9999-999</number>
</fax>
</person>

XStream을 사용하면 XML 객체를 직렬화 하는 방법도 있고, 역직렬화하는 방법(XML을 읽어서 프로그래밍하고싶을때 사용한다면..)도 있고
기본적으로 역직렬화를 하다보면 XStream방식으로 "
com.thoughtworks.xstream." element 이름으로 나오는 경우가 있는데 이때는 alias를 줘서 원하는 방식으로 바꾸는 방법도 있고, 또 annotation방법으로 편하게 줄 수도 있군요.

대충 예제를 보니 사용하기도 쉬운것 같습니다. 직렬화할 일이 있다면 써보는게 좋을 것 같군요~
 
  1. seattle
    2008/05/22 13:55 [Edit/Del] [Reply]
    한동안 블로그에 글이 뜸해서 궁금했었는데 열공중이셨군요. 화이팅~~
  2. 2008/05/23 10:46 [Edit/Del] [Reply]
    오호... 객체 내의 객체까지 직렬화가 가능하네요.
    음... 근데 Serializable과 관계없다면 텍스트 정보(숫자/문자열)만 직렬화가 가능한 듯 하네요.

    열공하시느라 바쁘신가보네요 ^^
  3. iolo
    2008/05/23 13:45 [Edit/Del] [Reply]
    간단하게 쓰기엔 꽤 편한데... 제대로 쓸려구 하면... 역시 복잡해진다는...-.-

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret

Java SE 6에 추가된 패키지중에 자바 코드에서 스크립팅 언어를 런타임 시에 호출하도록 도와주는 javax.script 패키지가 있다. 그렇구나!


동적인 언어를 동적으로 호출하기, Part 1: 자바 스크립팅 API (한글)

이 문서에서 코드를 다운로드 받아서 실행해보면 쉽게 이해가 된다. 내부는 잘은..모르겠지만,

이 패키지는 다른 스크립트 언어로 작성된 것을 공통 API를 사용하여 호출될 수 있도록 하는 class와 interface를 제공하기에 인터페이스를 통해 JVM안에서 스크립팅 코드를 작성할 수 있고 실행할 수 있다.

스크립팅 패키지를 사용할 수 있는 경우는

  • 완벽한 규칙 엔진에 의존하지 않고, 자바 언어보다 단순한 언어로 비즈니스 규칙을 작성한다.
  • 플러그인 아키텍처를 생성하여 사용자들이 즉석에서 애플리케이션을 커스터마이징 할 수 있도록 한다.
  • 기존 스크립트를 텍스트 파일들을 처리하거나 변형하는 스크립트 같은 자바 애플리케이션에 통합시킨다.
  • 프로퍼티 파일 대신 완전한 프로그래밍 언어를 사용하여 애플리케이션의 런타임 작동을 외부에서 설정한다.
  • 도메인 스팩의 언어를 자바 애플리케이션에 추가한다.
  • 스크립팅 언어를 사용하면서, 자바 애플리케이션을 프로토타이핑 한다.
  • 스크립팅 언어로 애플리케이션 테스트 코드를 작성한다.


중요 클래스와 인터페이스

import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");
// evaluate JavaScript code from String
engine.eval("print('Hello, World')");
}
}


ScriptEngineManager(Class) : 스크립트 엔진을 간접적으로 찾고 생성
스크립트-엔진 매니저들이 인스턴스화 되면, 등록된 모든 javax.script.ScriptEngineFactory 구현을 classpath에서 찾는다.

ScriptEngine(Interface) : 코드에선 ScriptEngine 인스턴스를 사용하여 스크립트를 실행하는데 스크립팅 코드와 기반 언어 인터프리터 또는 코드를 실행하는 컴파일러 사이의 중개자로서 작동한다.

ScriptEngine의 인스턴스를 이용하여 Java 메소드 안에서 JavaScript나 Ruby의 function 코드를 정의할 수도 있고 function을 통해 수행된 결과를 eval함수를 통해 출력창에 뿌릴수도 있다.
또, 스크립팅 코드에서 자바 메소드를 호출할 수도 있다.

Java Scripting Programmer's Guide
http://java.sun.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html

Script Engines in this project (so far!)
https://scripting.dev.java.net/


  1. seattle
    2008/05/01 09:22 [Edit/Del] [Reply]
    Hello, World 는 여전히 건재하군요 ^^

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret

[dW] 클래스 로딩 문제 분석하기

Posted at 2008/03/04 10:16// Posted in 나만의 작업/dW
클래스 로딩 문제 분석하기에 좋은 글이 있어서 올립니다
원문이 나온지는 좀 되었지만, 한번 읽어보기에 좋은 것 같습니다.
아래 내용은 저혼자 공부하면서 내용을 잠깐 정리해 본 것입니다.
Part 4로 이루어져 있기에 정리한 내용보다 더 방대한 내용이 담겨져 있습니다. ^^


클래스 로딩 문제 분석하기, Part 1: 클래스 로딩과 디버깅 툴 소개 (한글)
클래스 로딩 문제 분석하기, Part 2: 기본적인 클래스 로딩 예외(Exception) (한글)
클래스 로딩 문제 분석하기, Part 3: 특이한 클래스 로딩 문제 해결 (한글)
클래스 로딩 문제 분석하기, Part 4: 교착 상태와 제약 조건 (한글)

원문 시리즈
http://www.ibm.com/developerworks/views/java/libraryview.jsp?search_by=demystifying+class+loading+problems

Demystifying class loading problems, Part 1: An introduction to class loading and debugging tools
Demystifying class loading problems, Part 2: Basic class loading exceptions
Demystifying class loading problems, Part 3: Tackling more unusual class loading problems
Demystifying class loading problems, Part 4: Deadlocks and constraints


그 외 ClassLoader와 관련된 글
Java programming dynamics, Part 1: Classes and class loading

<Part 1 : 클래스 로딩과 디버깅 툴 소개>

클래스 로더는 클래스들을 Java Virtual Machine (JVM)에 로딩하는 일을 담당한다. 단순한 애플리케이션들은 자바 플랫폼에 내장되어 있는 클래스 로딩 장치를 사용하여 클래스들을 로딩한다. 보다 복잡한 애플리케이션들은 고유의 클래스 로더를 정의하기도 한다. 어떤 종류의 클래스 로더를 사용하든지 간에, 클래스 로딩 과정 동안 문제가 생길 수 있다. 이 같은 문제를 피하려면, 클래스 로딩의 구조를 이해해야 하여야 하며, 이를 통해, 문제가 발생하면 진단 기능과 디버깅 기술이 문제 해결에 도움이 될 것이다.

클래스 로딩은 로딩(loading), 링크(linking), 초기화(initializing) 단계로 나뉜다.

로딩 단계는 필요한 클래스 파일을 배치하고(각각의 classpath를 통해 검색함) 바이트코드로 로딩하는 단계이다. JVM의 로딩 프로세스는 클래스 객체에 매우 기본적인 메모리 구조를 제공한다.

링크(Linking)는 세 단계 중에서 가장 복잡한 단계이다. 다음과 같이 세 개의 주요 단계들로 나뉜다.

초기화(initialize) 단계 동안, 클래스 내에 포함된 정적 이니셜라이저(initializer)들이 실행된다. 이 단계의 끝에 가서는 정적 필드들이 기본 값으로 초기화 된다.

<Part 2: 기본적인 클래스 로딩 예외(Exception)>

ClassNotFoundException
ClassNotFoundException은 클래스를 로딩하려는 분명한 시도가 실패할 경우에 던져진다.

NoClassDefFoundError
자바 가상 머신(Java virtual machine) 또는 ClassLoader 인스턴스가 클래스 정의 중 로딩을 시도하고(정상적인 메소드 호출의 일환으로, 또는 새로운 식을 사용하여 새로운 인스턴스를 생성하는 것의 일환으로), 이 클래스에 대한 어떤 정의도 찾을 수 없을 때 예외(Exception)가 던져진다.

ClassCastException
이는 코드가 인스턴스가 아닌 것의 하위 클래스로 객체를 캐스팅(cast)할 때 생기는 예외(Exception)이다.

UnsatisfiedLinkError
JVM이 native로 선언된 메소드의 적절한 기본 언어 정의를 찾을 수 없을 때 발생한다.

ClassCircularityError
클래스나 인터페이스는 자기 자신의 하위 클래스나 하위 인터페이스가 되므로 클래스나 인터페이스는 로딩될 수 없다.

ClassFormatError
요청 받은 컴파일 된 클래스 또는 인터페이스를 지정하는 바이너리 데이터가 잘못 구성되었다.

ExceptionInInitializerError
  • 이니셜라이저가 E라는 예외(Exception)를 갑자기 던지고 종료하고, E의 클래스가 Error 또는 이것의 하위 클래스들 중 하나가 아니라면, ExceptionInInitializerError 클래스의 인스턴스가 E라는 인자와 함께 생성되어 E를 대신하여 사용된다.

  • JVM이 ExceptionInInitializerError 클래스에서 새로운 인스턴스를 만들기를 시도하지만 Out-Of-Memory-Error가 발생하여 그렇게 할 수 없을 경우, OutOfMemoryError 객체가 대신 던져진다


    <Part 3: 특이한 클래스 로딩 문제 해결>

    같은 듯한 다른 classpath문제

    classpathh에 /(slash)로 끝나는 경로와 slash가 없는 경로의 차이점

    예제에서의 결과

    file://C:/CL_Article/ClasspathIssues/cp/
    Class Z loaded.
    file://C:/CL_Article/ClasspathIssues/cp
    java.lang.ClassNotFoundException: Z
    at java.net.URLClassLoader.findClass(URLClassLoader.java:376)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:572)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
    at ClasspathTest.run(ClasspathTest.java:28)
    at ClasspathTest.main(ClasspathTest.java:36)


     URLClassloader는 약간 다른 매개변수를 전달한다. 첫 번째 클래스 로더 cl1에는 뒤에 /가 붙은 classpath가 주어진다. 두 번째 클래스 로더인 cl2의 classpath에는 /가 붙지 않는다. 클래스 로더는 /가 붙지 않은 경로는 JAR 파일을 참조하는 것으로 간주하기 때문에 이는 매우 중요한 차이이다. /로 끝나는 경로들만 디렉토리를 참조하는 것으로 간주된다.

    이러한 문제를 해결하는 방법은 각 경로의 끝에 /가 꼭 붙도록 해야 한다.


    가비지 컬렉션과 직렬화와 관련한 문제들

    가비지 컬렉터는 클래스 로더와 긴밀하게 상호 작동한다. 무엇보다도, 컬렉터는 클래스 로더 데이터 구조를 검사하여 어떤 클래스가 활성(live) 상태인지를 파악한다. 다시 말해서, 가비지 컬렉션 대상이 아닌지를 결정한다. 이는 예상치 못한 문제로 이어질 수 있다.

    클래스 로더가 참조되지 않을 때, 로딩되는 클래스들은 가비지 컬렉션 될 수 없다. ObjectStreamClass lookup table에서 SerializationClass 클래스에 대한 활성 참조가 있기 때문이다. ObjectStreamClass는 근원 클래스이기 때문에 가비지 컬렉션 대상이 될 수 없다. lookup table은 ObjectStreamClass의 정적 필드로부터 참조되고 이것의 인스턴스 보다는 클래스에 저장된다. 결국, SerializationClass에 대한 참조는 JVM의 수명 기간 동안 존재하며, 클래스는 가비지 컬렉션 대상이 될 수 없다. 중요한 것은, SerializationClass는 정의하는 클래스 로더에 대한 참조를 갖고 있기 때문에 완전하게 참조되지 않을 수는 없다.

    이러한 문제를 해결하려면, 직렬화 되지 않은 클래스들은 가비지 컬렉션 될 필요가 없는 클래스 로더(예를 들어, 시스템 클래스 로더)에 의해 로딩되어야 한다.

    <Part 4 : 교착 상태와 제약 조건>

  • 교착 상태 :

    두 개의 쓰레드가 각각 다른 클래스 로더에 잠금을 갖고 있고, 두 개의 쓰레드 모두 다른 쓰레드가 갖고 있는 잠금을 기다릴 때 발생한다. 두 개의 쓰레드는 다른 한쪽의 클래스 로더에 대한 잠금을 무한정 기다리기 때문에 교착 상태에 빠지게 된다. 이러한 교착 상태는 일반 델리게이션 모델이 우회(bypass)될 때 멀티 쓰레드 환경에서 발생할 수 있다.

    제약 조건 :

    두 개의 클래스 로더들이 같은 이름을 가진 다른 클래스들(다시 말해서, 다른 바이트코드)를 로딩하면, 클래스 로더 제약 조건이 이들 간 유형 미스매치(mismatch)가 없도록 보장해 준다.
    JVM 스팩에 따라, 다음과 같은 네 가지 조건들을 갖고 있으면 클래스 로더 제약 조건을 위반한 것이다.
    • N이라고 하는 Class C의 초기화 로더처럼 JVM에 의해 기록된 로더 L이 존재한다.

    • N이라고 하는 클래스 C'의 초기화 로더처럼 JVM에 의해 기록된 로더 L'이 존재한다.

    • 부과된 제약 조건에 의해 정의된 대등 관계가 N L = N L'를 함축하고 있다.
    • C != C'

    1. 2008/03/04 12:33 [Edit/Del] [Reply]
      자바 전문 블로거로 유명해 지겠어요.^^
    2. 2008/03/04 18:15 [Edit/Del] [Reply]
      @_@ 클래스 로딩도 파고들면 무지 복잡하네요.
      커스텀 클래스로더가 있다는 것도 신기하고...
      버리님 공부 열심히 하셔서 넘 멋져보여요 ㅎㅎ 부럽기도 하구요. ^^

    댓글을 남겨주세요

    Name *

    Password *

    Link (Your Homepage or Blog)

    Comment

    Secret

    Derby에서 paging구현..

    Posted at 2007/09/03 23:27// Posted in 나만의 작업
    JavaDB인 Derby에서 원하는 행부터 원하는 행까지 출력하고 싶어
    막연하게 Oracle에서 rownum을 쓰듯 where절에 rownum > 1 ....
    이렇게 썼더니, 당연히 rownum이란게 없다고 나오더라구요..

    설마, Oracle에서 rownum, Mysql에서 LIMIT가 derby에 없을까?
    쭉~~찾아보니 역시나 없다는 문서를 발견.ㅠㅠ

    ONJava.com의 Tuning Derby의 내용중...

    Many database servers support specialized SQL constructs that can be used to retrieve a specified subset of query results. For example, in MySQL you'll find the LIMIT and OFFSET keywords, which can be used in SELECT queries. So if you execute a query like this:

    select * from tbl LIMIT 50 OFFSET 100

    your result set will contain 50 rows starting
    from the 100th result, even if the original query returned 100,000
    rows. Many other database vendors provide similar functionality through
    different constructs.
    Unfortunately, Derby does not provide such functionality,
    so you have to stay with the original
    select * from tbl query and implement a paging mechanism on the application level.
    Let's look at the following example:
    Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
    Connection connection = DriverManager.getConnection(
    "jdbc:derby://localhost:1527/testDb;");
    Statement stmt = connection.createStatement();
    ResultSet rs = stmt.executeQuery("SELECT * FROM tbl");
    ArrayList allResults = new ArrayList();
    int i = 0;
    while (rs.next()) {
    if (i > 50 && i <= 100) {
    // O-R mapping code populate your row from result set
    DomainObject domainObject = populate(rs);
    allResults.add(modelObject);
    }
    i++;

    }
    System.out.println("Results Size: " + allResults.size());

    불행하게도, derby는 그런 메소드를 제공하지 않아서, full scan을 한후 그 결과값(ResultSet)으로
    어플리케이션 레벨에서 페이징 메카니즘을 구현해야한다고 하네요.
    구현은 그리 어렵지 않지만, rownum과 같이 편리한 메소드를 왜 아직 제공안하는지.ㅠㅠ

    뒤에 더 문서를 보면 OutofMemoryError에 대해 안전하다고 하지만
    그래도 찜찜하면 트릭을 써서 명시적으로 얼마까지 로우를 가져올지

    stmt.setMaxRows(101);

    이 함수를 써서 이용하라고 합니다..

    다른 문서 JavaDB FAQ 내용중에 얼핏보았는데 아직 rownum과 같은 메소드를 현재 제공하지는 않지만
    언젠가는 제공하기를 고려하고 있다고 합니다..


    1. 2007/09/04 01:54 [Edit/Del] [Reply]
      99990 ~ 100000 번째 ROW를 가져오려면 setMaxRows()도 100000을 잡아야 되는걸로 보이는데요;;
      setMinRows() 가 있는지는 Derby를 안써봐서 모르겠지만...
      일단 없다면 100000개의 데이터 압박이 있군요.
      어찌됐던 풀스캔의 압박은...-_-;;
    2. 2007/09/04 02:36 [Edit/Del] [Reply]
      워워워~ 그렇군요~
      그럼 그냥 where 절을 잘 적어서 limit 효과를 볼 수 있지 않을까용? ㅋ
      걍 그냥 생각입니다. ㅋㅋ
      • 2007/09/04 09:42 [Edit/Del]
        where절을 잘 적는다고 해도 그 where절에 해당하는
        row가 정말 많을때 rownum이 없을때의 효과를 톡톡히
        치르겠죠...
    3. seattle
      2007/09/04 11:33 [Edit/Del] [Reply]
      DB와 페이징 구현은 참 오묘한(?) 관계가 있는듯 싶습니다. 마치 고양이와 개의 사이랄까요..
    4. geust
      2010/05/28 17:13 [Edit/Del] [Reply]
      row_number()를 이용하세요.

    댓글을 남겨주세요

    Name *

    Password *

    Link (Your Homepage or Blog)

    Comment

    Secret

    awt와 swing의 차이점

    Posted at 2007/06/19 21:26// Posted in 나만의 작업
    java로 응용프로그램을 만들어본게 손에 꼽을 정도라서 awt와 swing의 확실한 차이점을 몰랐습니다. 오늘 배운내용을 이번기회에 확실히 알고 넘어가기 위해서,,

    AWT는 Abstract Windows Toolkit의 약자로 '추상 윈도우 개발 도구'라는 뜻으로
    운영체제의 자원을 이용하여 control의 외형을 형성합니다.

    즉 MS의 윈도우와 유닉스계열에서 GUI가 비슷하게는 나타나지만 같게 보이지는 않습니다.
    그래서 'abstract'인거지요.
    예로 button component를 생성하면 운영체제마다 그 버튼의 모양과 크기는 조금씩 다르게 나타납니다. 이것이 peer를 통한 component의 생성으로 나타나는 문제입니다.
    (현재 운영제체의 각 component를 peer component라고 합니다.AWT는 기반운영시스템에서 Native code를 빌려서 GUI를 생성시킨 Peer 구조를 가집니다.)

    운영체제에서 표현하고자 하는것을 중립적으로 표현하기에는 좋지만
    다양하게 표현하기엔 힘들다는것이 단점입니다. 그래서 예쁘게 나오기도 힘들구요
    제한된 GUI 컴포넌트, 레이아웃 매니저, 이벤트를 가진 매우 단순한 툴킷입니다.

    더 자세한 설명

    more..



    Swing(Part of Java Foundation Classes)은 운영체제에 구애받지 않고 구현할 수 있다.
    기존의 awt는 해당 운영체제의 GUI를 빌려쓰는 형식이지만 Swing은 pure java로만
    구성되어 있기때문에 리눅스든 윈도우든 솔라리스든간에 인터페이스가 동일하다

    다만 단점은 AWT보다 느리다는 것.

    AWT component is also known as heavyweight component because all AWT components have its peer, the native GUI components. For example, Button, TextArea, and Label are heavyweight components. They have peer in C code on the native platform.

    Swing was developed to enhance the AWT toolkit by allowing user to create lightweight components which do not have the native GUI component. For example, JTabbedPane is a lightweight component of Swing. It has no peer in C code on the native platform.


    참고로 eclipse는 swt(Standard Windows Toolkit)로 GUI가 개발되었습니다.

    java에서 GUI를 지원하기 위한 도구로 sun에서 개발한 Swing이 널리 사용되고 있었는데, IBM에서 통합개발 플랫폼인 Eclipse를 개발하면서 Swing 대신 자체적으로 개발한 GUI라이브러리를 제작합니다.

    swing과 swt의 비교
    Swing : J2SE를 위한 GUI 툴킷
    SWT : IBM의 공개 프로젝트인 Eclipse 플랫폼의 제작을 위해 별도로 개발된 라이브러리

    SWT는 Standard Widget Toolkit의 줄임말로 각 운영체제자체에서 제공되는 위젯 툴킷을 통합한 그래픽 라이브러리다. 이는 각 타겟 플렛폼에 꽤나 의존적이 될 수도 있음을 의미하지만, OS독립적인 API를 제공함으로써 이 문제를 해결하고 있다. 이들 API는 목표가 되는 운영체제 시스템의 GUI코드를 wrapper함으로써 개발자 입장에서는 운영체제에 신경쓰지 않고 동일한 코드를 유지할 수 있게 된다.


    덧붙여 설명하자면, Swing은 모든 위젯이 운영체제와 별개를 사용하는데(자바의 모토가 One make All use 아니던가) 그렇기때문에 Swing의 GUI는 웬지 눈에 낯설고 어색해 보이는 면이 있어왔다. 그러나 SWT는 가능한한 사용할 수있는 모든 Native Widget은 사용하고, 그러하지 않는 부분만 자바의 자체 위젯을 사용한다. 때문에 최대한 그 OS의 Native GUI와 비슷한 모습을 보여주는것이다.(Native에서 제공하지 않는 자체 위젯까지 포함하므로 때론 더 이쁠수도 있겠다. 물론 반대인 경우도 있겠지만).


    그럼 자바가 시스템에 독립적이지 않은게 아닌가? 하고 반문할지 모르지만 위에 설명된 바와같이 공통적인 API를 사용하므로서 (Abstract Layer라고 볼 수 도 있겠다) OS가 다르다고 해서 소스코드의 변경을 필요로 하지 않는것이다. (VM차원에서 Native Widget를 해당 API로 랩핑해주므로)




    참고한 URL

    http://www.javastudy.co.kr/docs/yopark/chap08/chap08.html#_Toc466766198
    http://abangwithjava.blogspot.com/2006/09/java-gui-awt-swing-and-swt.html
    http://blog.naver.com/zzanggoosoft?Redirect=Log&logNo=30009621746
    http://www.ibm.com/developerworks/java/library/os-swingswt/index.html

    Tag AWT, java, swing, swt, 자바
    1. 2007/06/19 23:55 [Edit/Del] [Reply]
      그렇군요. 저도 웹만 후벼파다보니 이런건 잘 모릅니다. 예전에 봤었어도 다 까먹었고요.


      내가 가진 지식은 백사장의 모래알 한줌이나 될런지 모르겠네요.. 라는 생각이 문득 스쳐지나갑니다.
      • 2007/06/20 09:52 [Edit/Del]
        공부는 정말 끝이 없는것 같아요
        하루하루 변하는 IT에서는,ㅋㅋ
        그래도 Belle님은 다 아시자나요..ㅋㅋ
    2. 2007/06/25 23:47 [Edit/Del] [Reply]
      헉; 버리님은 Java 세대 아니신가요? +_+
      • 버리
        2007/06/26 00:50 [Edit/Del]
        Java 세대는 어떤 세대인지..이해가 잘 안가요..ㅠㅠ
      • 2007/06/28 17:22 [Edit/Del]
        아, 그게요. ^^;
        학부 시절에 데이터 구조 같은 과목에서 처음 배우는 언어가 몇년 전에는 C였는데, 요즘에는 자바잖아요. 졸업할 때까지 C로 코딩을 한번도 안해본 학생이 있을 정도로 자바가 일반화되어 있더군요. 그래서 요즘 세대를 Java 세대라고 한데요. ㅎㅎ
      • 2007/06/28 23:27 [Edit/Del]
        그럼 저 정말 java세대네요
        전 C도 아주 기초적인것만 배워서..ㅎㅎ

    댓글을 남겨주세요

    Name *

    Password *

    Link (Your Homepage or Blog)

    Comment

    Secret