2013-07-25 2 views
1

getValue() 메서드에 액세스 할 수 있도록 ChangeEvent 객체를 JSpinner 객체로 다시 캐스팅하지 않고 e.getSource()가 이벤트를 생성하는 데 사용 된 유형의 사전 캐스트 객체를 반환하지 않는 이유는 무엇입니까? ? e.getSource()의 첫 번째 용도는 JSpinner가 사용되고 있다는 것을 분명히합니다. 왜 다시 캐스트하지 않는 것이 좋을까요? 그것은 더 간단 할 것 같습니다. 나는 이것을하지 않는 것이 안전 이유라고 가정하고 있지만, 나는 그것이 기본 사용으로 가지는 것이 나쁜 것이되는 구체적인 예를 보거나 들으려고한다.ChangeListener의 getSource()가 이벤트를 생성하는 데 사용 된 유형의 사전 캐스트 객체를 반환하지 않는 이유는 무엇입니까?

안전하지 않습니까? 그것은 단지 나쁜 건축인가?

public class SpinnerPanel extends JPanel implements ChangeListener { 

... 

SpinnerPanel() 
{ 
    birthdaySpinner.addChangeListener(this); 
    add(birthdaySpinner); 
} 

@Override 
public void stateChanged(ChangeEvent e) 
{ 
    System.out.println(e.getSource()); 

    JSpinner spinner = (JSpinner)e.getSource(); 
    System.out.println(spinner.getValue()); 
} 
} 
+4

ChangeListener는 여러 다른 구성 요소에서 모두 사용할 수 있으므로 원본 개체에 대한 자체 요구 사항이 있습니다. API가 설계되면 제네릭이 존재하지 않고 API를 변경하면 현재 실행중인 생산 코드에 영향을 미칠 수 있습니다. – MadProgrammer

+1

아, 알았습니다. 리스너가 여러 항목에 연결되어있는 곳에서 많은 코드를 작성했다고는 생각하지 않지만 귀하의 의견은이를 수행 할 수 있음을 상기시켜주었습니다. 이는 추론을 간결하게 설명합니다. 조금 바보 같아서 물어 보았지만, 적어도 그 작은 맛있는 음식은 지금 내 머리 속에 버려졌습니다. – Azoreo

+1

포인트를 정교하게 만들 수있는 특정 코드 스 니펫을 가지고 계신가요? 나는 여전히 그것에 대해 생각하고 있고 그것을 시각화하는 데 약간의 어려움을 겪고있다. – Azoreo

답변

2

소스가 JSpinner 런타임에 알려진 것 사실. 사용자가 기술하는 "자동 형변환"의 종류는 컴파일 시간에 제네릭을 사용하여 가능하지만 그 시점에는 청취자가 어디로 끝날지 알 수 없습니다. 예를 들어 회 전자를 가져 와서 모든 수신기의 목록을 가져온 다음이 수신기를 확인란과 같은 다른 위젯에 추가 할 수 있습니다. 컴파일시 컴파일러에게이 일이 발생하지 않는다는 것을 알려주는 코드는 없으므로 컴파일러에서 소스가 항상 스피너가 될 것이라고 알려줄 수는 없습니다.

이론적으로는 어떤 방식 으로든 제네릭을 사용할 수 있습니다. T 클래스의 구성 요소에서 변경된 내용은 ChangeEvent<T> 일 수 있습니다. ChangeListener<T>의 메소드는 stateChanged(ChangeEvent<? extends T>) 일 수 있습니다. 그렇다면 클래스 T의 주어진 구성 요소의 모든 청취자에 대한 유형은 무엇입니까? List<ChangeEvent<T>> 인 경우 해당 목록에 일반 ChangeListener<Object>을 추가 할 수 없습니다. 따라서 List<ChangeEvent<? super T>>이어야합니다. 그러나 어떤 구성 요소에 그러한 목록이있는 경우 제네릭 방식과 같은보다 구체적인 유형 대신 모든 파생 된 구성 요소에 대해 동일한 유형이됩니다.

이 제네릭 방식을 사용하면 코드 작성 및 유지 관리가 훨씬 어려워지고 허점을 어느 장소에 남겨두고 아마도 이전 버전과의 호환성 측면에서 끔찍할 것이며 전체적으로는 그렇지 않을 것이라고 생각합니다. 노력할 가치가있는.