2013-09-25 4 views
1

메서드에서 수정할 수없는 맵을 반환하고 있습니다. 런타임 오류가 아니라 반환 된 맵을 수정하려고하는 코드에 컴파일 타임 오류가 발생하는지 확인하려면 어떻게해야합니까?해당 메서드를 선언하는 방법 Collections.unmodifiableMap

내 클래스 :

Foo foo = new Foo(); 
Map<String, Bar> m = foo.getMap(); 
m.put('key',null); // user should be notified that the map is unmodifiable here, not at run time 

내가 반환 형식을 변경할 수 있습니다

public class Foo 
{ 
    private final Map<String, Bar> aMap; 

    public Foo() 
    { 
    ... 
    } 

    public Map<String, Bar> getMap(){ 
     return Collections.unmodifiableMap(aMap); 
    } 
} 

내가이 컴파일시 에러를 만들려면? 적절한 주석을 추가 할 수 있습니까?

+0

메서드의 반환 형식이 java.util.Map 인 경우이를 수행 할 방법이 없습니다. 반환 형식은'Map'을 래핑하는 사용자 정의 클래스로만 변경할 수 있습니다. – jlordo

+0

괜찮 았는데 반환 유형을 어떻게 변경합니까? – Boundless

+0

아마도이 경우 전체지도를 반환하면 안됩니다. – doctorlove

답변

4

당신은

class ReadOnlyMap<K, V> { 

    private final Map<K, V> map; 

    public ReadOnlyMap(Map<K, V> map) { 
     this.map = map; 
    } 

    public V get(Object key) { 
     return map.get(key); 
    } 

    // also implement size() method 
    // and everything else you want to expose 
} 

같은 클래스를 생성하고 메서드의 반환 형식으로 사용할 수 있습니다. 그런 다음 방법은

public ReadOnlyMap<String, Bar> getMap() { 
    return new ReadOnlyMap(aMap); 
} 

이 그들이 불변 클래스의 인스턴스하지 않으면, 값 오브젝트를 돌연변이 발신자를 방해하지 않습니다주의 할 것이다.

+2

다른 답변에서 지적한 것처럼 다음에주의해야한다. "values ​​() 및 entrySet() 메서드가 수정 가능한 컬렉션을 반환하므로주의해야한다. 반환 된 가치를 감쌀 필요가 있습니다. " – StormeHawke

0

할 수 없습니다.

불가능한 Collection은 구현 선택이 아닌 유형입니다.

/** 
* Gets the map 
* @returns An unmodifiable Map 
*/ 
public Map<String, Bar> getMap(){ 
    return Collections.unmodifiableMap(aMap); 
} 
+0

그래서 다른 개발자들이 put을 호출하지 않도록 알릴 수 있습니까? – Boundless

+0

@ 무한. 'getMap()'메쏘드를 문서화하여'Unmodifiable' 맵을 반환하도록 지정할 수 있습니다. 그 이상을 달성 할 수는 없습니다. –

+0

Collections.unmodifiableMap (aMap)의 반환 유형은 구체적인 클래스입니다 (http://www.docjar.com/docs/api/java/util/Collections$UnmodifiableMap.html). 그냥 패키지 전용이고 java.util 패키지 외부에서 볼 수 없다. – krishnakumarp

2

기본지도 수정할 수, 기간 :

당신이 할 수있는 최선은, 자바 독과 같은 그것을 문서화하는 것입니다.

수정할 수 없도록하려면지도 변수로 사용하는 클래스를 작성하고 다시 필요한 모든 메서드를 구현하여지도에 전달해야합니다.

.put() 메소드를 원하지 않으므로이 메소드를 건너 뜁니다.

0

표준 클래스는 사용할 수 없습니다. 표준 클래스를 사용하면 수정할 수 없다는 것을 알 수있는 유일한 방법은이를 수정하고 UnsupportedOperationException을받는 것입니다.

보통 Map을 내부적으로 사용하는 (변경 불가능할 수도 있음) 고유 한 UnmodifiableMap 구현을 작성하여 컴파일 시간을 확인할 수 있습니다. 일반적인 "읽기"작업을 수행하며 기본 Map에 위임됩니다. 일반적인 "쓰기"작업을 수행하지 않습니다. 다른 코드와의 상호 운용성을 높이기 위해 기본 코드 인 Map (또는이 코드의 복사본)을 반환하는 방법을 원한다고 생각합니다.

1

Map 인터페이스의 모든 읽기 방법을 갖고 있지만 쓰기 방법이없는 UnmodifiableMap 개체를 만들 수 있습니다. 이 객체는 원하는지도를 래핑합니다. 당신이 너무 자신의 반환 값을 포장해야하므로

public class UnmodifiableMap<K, V> { 

    private final Map<K, V> map; 

    public UnmodifiableMap(final Map<K, V> map) { 
     this.map = map; 
    } 

    public boolean containsKey(final K key) { 
     return map.containsKey(key); 
    } 

    public V get(final K key) { 
     return map.get(key); 
    } 

    // And so on. 

} 

는, 값()와 entrySet() 메소드가 수정 컬렉션을 반환주의 :이 같을 것이다.

+0

가능한 한'Map'을 따르고 싶다면'get()'메쏘드는'K'가 아니라'Object'를 매개 변수로 취해야합니다;) 그렇지 않으면 그 길입니다. – jlordo

0

이것은 사용자가 요구하는 것 근처에있는 것처럼 보입니다. 그것은 오류를주지는 않지만 경고를줍니다!

public class Solid { 
    // My map has no put. 
    public interface Map<K, V> extends java.util.Map<K, V> { 
    /** 
    * Put to the Map. 
    * 
    * @deprecated SolidMap is unmodifiable. put() will fail! 
    */ 
    @Deprecated 
    @Override 
    V put(K key, V value); 

    } 

    // Could also do this for lists etc. 

    // Helper wrappers from each kind of map. 
    public class HashMap<K, V> extends java.util.HashMap<K, V> implements Solid.Map<K, V> { 
    } 

    public class TreeMap<K, V> extends java.util.TreeMap<K, V> implements Solid.Map<K, V> { 
    } 
    //... 

    // Test only. 
    public void test() { 
    Solid.Map<String, String> sm = new Solid.HashMap<>(); 
    // Warning that put is deprecated! 
    String put = sm.put("Key", "Value"); 
    } 

    public static void main(String args[]) { 
    try { 
     new Solid().test(); 
    } catch (Throwable t) { 
     t.printStackTrace(System.err); 
    } 
    } 

}