天天看點

泛型中的方法沖突

class LastError<T> {
    private T lastError;
    
    public void setError(T t){
        lastError = t;
        System.out.println("LastError: setError");
    }
}

class StrLastError<S extends CharSequence> extends LastError<String>{
    public StrLastError(S s) {}

    public void setError(S s){
        System.out.println("StrLastError: setError");
    }
}

class Test {
    public static void main(String[] args) {
        StrLastError<String> err = new StrLastError<String>("Error");
        err.setError("Last error");
    }
}      

這段代碼報錯, 原因是:StrLastError.setError(S) 沒有形成重載。

因為StrLastError裡面有2個方法,

setError(java.lang.CharSequence)

setError(java.lang.Object)

對于err.setError(“last error”) 都是模糊的,故報錯。

但如果把<S extends CharSequence>去掉,即可成功。

即把代碼改為

class LastError<T> {
    private T lastError;

    public void setError(T t){
        lastError = t;
        System.out.println("LastError: setError");
    }
}

class StrLastError extends LastError<String>{
    public StrLastError(String s) {}

    public void setError(String s){
        System.out.println("StrLastError: setError");
    }
}

public class Test {
    public static void main(String[] args) {
        StrLastError err = new StrLastError("Error");
        err.setError("Last error");
    }
}      

StrLastError不再是泛型。虛拟機生成橋方法如下:

class StrLastError extends LastError<java.lang.String> {

  public StrLastError(java.lang.String);

  public void setError(java.lang.String);

  public void setError(java.lang.Object);//裡面實質調用上面那個方法

}

就是說,如果StrLastError還是泛型類的話,有兩個方法對于setError(String)都是可以滿足的,就沖突了。

若把LastError改為T extends Number, 然後StrlastError改為繼承LastError<Integer>也是可以的。

public class Test {
    public static void main(String[] args) {
        StrLastError err = new StrLastError("Error");
        err.setError("Last error");
    }
}

class LastError<T extends Number> {
    private T lastError;

    public void setError(T t){
        lastError = t;
        System.out.println("LastError: setError");
    }
}

class StrLastError<S extends CharSequence> extends LastError<Integer>{
    public StrLastError(S s) {}

    public void setError(S s){
        System.out.println("StrLastError: setError");
    }
}