문제

항목 #29 Effective Java에서는 "유형이 안전한" 이기종 컬렉션을 구현하는 방법을 제시합니다. 이는 기본적으로 다음과 같이 요약됩니다.

public Class HeterogeneousContainer {
    private Map<Class<?>, Object> container = new HashMap<>();

    public <T> put(Class<T> type, T instance) {
        container.put(type, instance);
    }

    public <T> T get(Class<T> type) {
        //essentially just 
        //      return (T) container.get(type);
        return type.cast(container.get(type));
    }
}

그러면 (제 생각에) 다음과 같이 (생산자에 의해) 사용됩니다:

List<HeterogeneousContainer> resultSet = new ArrayList<>();
...
resultSet.add(new HeterogeneousContainer());
...
resultSet.get(rowIndex).add(Column1.class, column1Value);
resultSet.get(rowIndex).add(Column2.class, column2Value);
...

그리고 (소비자에 의한) 다음과 같습니다:

for(HeterogeneousContainer row:resultSet) {
    Column1 column1Value = row.get(Column1.class);
    Column2 column2Value = row.get(Column2.class);
    ...
    //do something with the columnValues
}

이제 내 질문은 이것이 유형 안전으로 간주되는 이유입니다.열 이름을 맵에 넣거나 일반 이름을 사용하는 것보다 이것이 더 나은 점은 무엇입니까? List/List<Object> 그리고 인덱스로 열을 찾으시나요?

이것이 JDBC ResultsSets의 .getString/.getInt/.getXXXX 접근 방식을 어떤 방식으로든 효과적으로/실질적으로 개선합니까?

도움이 되었습니까?

해결책

이 클래스는 런타임 중에 클래스 캐스팅을 수행하는 동안에도 이 안전하지 않은 동작이 캡슐화되어 관찰할 수 없기 때문에 형식이 안전한 것으로 간주됩니다.

  • 그만큼 container 필드는 비공개이므로 유형 안전성을 고려할 때 이 클래스 내부의 코드만 확인하면 됩니다.
  • 그만큼 put 메소드는 type 태그 쌍을 삽입합니다. T 그리고 유형의 요소 T.이곳이 유일한 곳이다. container 업데이트되며 삽입된 요소에 올바른 유형 태그가 있음이 (컴파일 시) 보장됩니다.
  • 그만큼 get 방법 하다 안전하지 않은 방식으로 클래스 캐스팅(return type.cast(container.get(type))) 그러나 그것이 확실하다면 container 를 통해서만 수정됩니다. put, 실패할 수 없습니다.그리고 위에서 우리는 그것을 보았습니다. put 물론 그렇게 할 수 있는 유일한 방법은 이 수업입니다. ~이다 사용자에게 형식이 안전합니다.

진실을 말하자면, 정말로 원한다면 리플렉션을 사용하여 이 클래스의 유형 안전성을 깨뜨릴 수 있습니다.일반적으로 이것은 중요하지 않습니다. 왜냐하면 당신은 당신의 클래스를 방어하기를 원하기 때문입니다. 실수로 오용됨 오히려 의도적으로 손상됨.그러나, 당신이 읽어보면 효과적인 자바 게다가 그러한 공격을 방어하는 것이 훨씬 더 복잡하다는 것을 알게 될 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top