簡體   English   中英

Map的Java泛型問題

[英]Java generics problem with Map

我有這個不應該編譯。

public boolean foo(final Map<String, String> map) {
     map.get(1);   // No error here?
}

get方法接受一個Object,因此1被自動裝箱到一個Integer並且編譯得很好。 盡管如此,你總是會得到null作為回應。

這樣做是為了向后兼容。

// Ideal Map:
public V get(K key) {
 // impl here
}

// what we have
public V get(Object key) {
 // impl here
}

蠍子的例子

import java.util.*;
class ScorpMain {

    /* This interface just has a single method on it returning an int */
    static interface SomeInterface {
        int foo();
    }

    /**
     * ExampleKey has an int and a string. It considers itself to be equal to
     * another object if that object implements SomeInterface and the two have
     * equal foo values. It believes this is sufficient, as its sole purpose is
     * to calculate this foo value.
     */
    static class ExampleKey implements SomeInterface {
        int i;
        String s;
        ExampleKey(int i, String s) { this.i = i; this.s = s; }
        public int foo() { return i * s.length(); }
        public int hashCode() { return i ^ s.hashCode(); }
        // notice - equals takes Object, not ExampleKey
        public boolean equals(Object o) {
            if(o instanceof SomeInterface) {
                SomeInterface so = (SomeInterface)o;
                System.out.println(so.foo() + " " + foo());
                return so.foo() == foo();
            }
            return false;
        }
    }

    /**
     * The ImposterKey stores it's foo and hash value. It has no calculation 
     * involved. Note that its only relation to ExampleKey is that they happen
     * to have SomeInterface.
     */
    static class ImposterKey implements SomeInterface {
        int foo;
        int hash;
        ImposterKey(int foo, int hash) { this.foo = foo; this.hash = hash; }
        public int foo() { return foo; }
        public boolean equals(Object o) {
                SomeInterface so = (SomeInterface)o;
                return so.foo() == foo();
        }
        public int hashCode() { return hash; }
    }

    /**
     * In our main method, we make a map. We put a key into the map. We get the
     * data from the map to prove we can get it out. Then we make an imposter, 
     * and get the data based on that. 
     * The moral of the story is, Map.get isn't sacred: if you can trick it 
     * into thinking that the object inside is equal to the object you give it 
     * in both equality and hash, it will give you the resulting object. It 
     * doesn't have anything to do with the type except that a given type is 
     * unlikely to be equal to another object that isn't of the given type.
     * This may seem like a contrived example, and it is, but it is something 
     * to be conscious of when dealing with maps. It's entirely possible you 
     * could get the same data and not realize what you're trying to do. Note 
     * you cannot ADD the imposter, because that IS checked at compile time.
     */
    public static void main(String[] args) {
        Map<ExampleKey,String> map = new HashMap<ExampleKey,String>();
        ExampleKey key = new ExampleKey(1337,"Hi");
        map.put(key,"Awesome!");
        String get = map.get(key);
        System.out.println(get); // we got awesome
        ImposterKey imposter = new ImposterKey(2674,3096); // make an imposter
        String fake = map.get(imposter);
        System.out.println(fake); // we got awesome again!
    }
}

從Java 6開始,您編寫的行完全等同於:

public boolean foo(final Map<String, String> map) {
    map.get(Integer.valueOf(1)); // compiles fine of course!
}

他們稱之為“自動裝箱”。 另一方面是“autounboxing”,即:

public int bar(final Map<String, Integer> map) {
    return map.get("bar");
}

這一行相當於:

return map.get("bar").intValue();

當在地圖中找不到請求的密鑰時,有時會導致相當神秘的NullPointerException。 對於剛接觸這個概念的程序員來說,這是一個常見的陷阱。

希望有所幫助。

我有這個不應該編譯。

為什么不?

.get()的定義表示它找到了鍵,使得給定的對象等於鍵。 是的, 在這種情況下,我們知道對象是一個Integer ,而Integer.equals()方法總是為String對象返回false。 但一般來說,對於不同類的兩個對象,我們不知道這一點。 事實上,Java庫中有些情況需要不同類的對象相等; 例如,如果列表的內容相同且順序相同,則java.util.List要求列表相等,而不管類是什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM