Java謎題7:餅乾-解決方案

jdon發表於2019-09-24

乍一看,cookiemonster.eat需要返回一個負長度的String。仔細看,有兩個單獨的要求:第一次呼叫eat時,它需要返回一個空String;第二次,它需要返回一個負值length()。

訣竅是,泛型方法的返回型別可能會有所不同,具體取決於使用它的型別上下文。為了證明這一點,讓我們來看一個示例java.util.Collections:<T> List <T> emptyList()。在方法簽名中,<t>表示方法上有型別變數t,list<t>是返回型別。您可以將其用作List<String> strings = Collections.emptyList();。這是因為型別推斷確保返回型別(list<t>)中的t調整為它被分配給的變數型別(list<string>)。如果沒有上下文(未分配任何內容),則推斷的型別將是 Object(T的隱式上界)。在Collections.emptyList().size()中,例如emptyList()返回一個List<Object>。

回到我們的CookieMonster,我們可以讓eat返回上下文期望它返回的任何內容:static<c>ceat(string cookie)。就像一塊神奇的餅乾。如果你認為是“巧克力”並把它放進嘴裡,那它就是巧克力餅乾。在count中,它被分配給一個String,它會變成一個Stringcookie(我不想知道那是什麼味道)。這是一個開始,但是在cookiemonster.eat(nocookie).length()中,沒有上下文,所以它變成了沒有length()方法的Object ,並且無法編譯。

我們透過在C上設定一個bound來修復這個問題。要編譯兩個eat呼叫,bound必須是String的超類,並且有一個length()方法。有一種型別:charsequence。因此,我們將型別變數<c>替換為<c extends charsequence>。在第一次呼叫中,eat(“cookie”)必須返回空值String,在第二次呼叫中,eat(“”)必須返回長度為負的charsequence:

package monster;
 
public class CookieMonster {
    public static <C extends CharSequence> C eat(String cookie) {
        return (C) (cookie.length() > 0 ? "" : new CharSequence() {
            public int length() {
                return -1;
            }
 
            public char charAt(int index) {
                throw new UnsupportedOperationException();
            }
 
            public CharSequence subSequence(int start, int end) {
                throw new UnsupportedOperationException();
            }
        });
    }
}

 

相關文章