我有一个基本的class BaseNewsItem,以及2个派生类NewsItemMovieNewsItem。然后,有一个MovieListingFeed类,其中包含一个MovieNewsItem列表并且是可打包的。它可以在任何活动需要时将此列表打包。

protected MovieNewsListingFeed(Parcel in) {
    this.pg = in.readParcelable(PageDetail.class.getClassLoader());
    this.items=new ArrayList<>();
    in.readTypedList(items, MovieNewsItem.CREATOR);
}


我在此行收到错误消息:

in.readTypedList(items, MovieNewsItem.CREATOR);


错误:

Error:(60, 11) error: method readTypedList in class Parcel cannot be applied to given types;   required: List<T>,Creator<T>   found: ArrayList<CAP#1>,Creator<CAP#2>   reason: inferred type does not conform to equality constraint(s)   inferred: CAP#2   equality constraints(s): CAP#2,CAP#1   where T is a type-variable:   T extends Object declared in method <T>readTypedList(List<T>,Creator<T>) where CAP#1,CAP#2 are fresh type-variables:   CAP#1 extends BaseNewsItem from capture of ? extends BaseNewsItem   CAP#2 extends BaseNewsItem from capture of ? extends BaseNewsItem


我是Generics的新手,因此当我搜索上述错误时,并没有完全发布解决方案。我只是添加了将ArrayList<MovieNewsItem>转换为ArrayList<BaseNewsItem>所需的内容。

MovieNewsItem类中的相关代码:

public static final Creator<? extends BaseNewsItem> CREATOR = new Creator<MovieNewsItem>() {
    public MovieNewsItem createFromParcel(Parcel source) {
        return new MovieNewsItem(source);
    }

    public MovieNewsItem[] newArray(int size) {
        return new MovieNewsItem[size];
    }
};


让我知道是否需要其他代码片段。

更新1 :(来自Android框架的readTypedList。)

public final <T> void readTypedList(List<T> list, Parcelable.Creator<T> c) {
    int M = list.size();
    int N = readInt();
    int i = 0;
    for (; i < M && i < N; i++) {
        if (readInt() != 0) {
            list.set(i, c.createFromParcel(this));
        } else {
            list.set(i, null);
        }
    }
    for (; i<N; i++) {
        if (readInt() != 0) {
            list.add(c.createFromParcel(this));
        } else {
            list.add(null);
        }
    }
    for (; i<M; i++) {
        list.remove(N);
    }
}


MovieNewsListingFeed.java(问题文件):

public class MovieNewsListingFeed implements Parcelable {

PageDetail pg;

public void setItems(ArrayList<? extends BaseNewsItem> items) {
    this.items = items;
}

ArrayList<? extends BaseNewsItem> items;

public ArrayList<? extends BaseNewsItem> getItemsTemp() {
    return itemsTemp;
}

public void setItemsTemp(ArrayList<? extends BaseNewsItem> itemsTemp) {
    this.itemsTemp = itemsTemp;
}

ArrayList<? extends BaseNewsItem> itemsTemp;

public ArrayList<? extends BaseNewsItem> getItems() {
    return items;
}

public PageDetail getPg() {
    return pg;
}


@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeParcelable(this.pg, flags);
    dest.writeTypedList(items);
}

public MovieNewsListingFeed() {
}

protected MovieNewsListingFeed(Parcel in) {
    this.pg = in.readParcelable(PageDetail.class.getClassLoader());
    this.items = new ArrayList<>();
    in.readTypedList(items, MovieNewsItem.CREATOR);
}

public static final Parcelable.Creator<MovieNewsListingFeed> CREATOR = new Parcelable.Creator<MovieNewsListingFeed>() {
    public MovieNewsListingFeed createFromParcel(Parcel source) {
        return new MovieNewsListingFeed(source);
    }

    public MovieNewsListingFeed[] newArray(int size) {
        return new MovieNewsListingFeed[size];
    }
};


}

MovieNewsItem.java:

public class MovieNewsItem extends BaseNewsItem implements Parcelable {
String hl;
String imageid;
String syn;
String id;
String dm;
String tn;
String dl = "";
String sectionHeader;
String upd;
String ud;

private int validListPosition = -1;

public int getValidListPosition() {
    return validListPosition;
}

@Override
public void setTitle(String title) {

}

@Override
public void setId(String id) {

}

@Override
public void setDate(String date) {

}

@Override
public void setNewsType(int newsType) {

}

public String getFormatedDate() {
    return formatedDate;
}

String formatedDate;

int position;
int newSectionType = NewsType.CONTENT_TYPE_NEWS;
String dayHeading;

public int getPosition() {
    return position;
}

public void setPosition(int position) {
    this.position = position;
}


public void setNewSectionType(int newSectionType) {
    this.newSectionType = newSectionType;
}

public String getDayHeading() {
    return dayHeading;
}

public void setDayHeading(String dayHeading) {
    this.dayHeading = dayHeading;
}

@Override
public void setValidListPosition(int listPosition) {

}

public String getWu() {
    return wu;
}

String wu;


public String getHl() {
    return hl;
}

public String getImageid() {
    return imageid;
}

public String getSyn() {
    return syn;
}

public String getId() {
    return id;
}

public String getDm() {
    return dm;
}

public String getTn() {
    return tn;
}

public String getDl() {
    return dl;
}

public String getSectionHeader() {
    return sectionHeader;
}


public MovieNewsItem() {
}

@Override
public String getTitle() {
    return (!TextUtils.isEmpty(getSyn())) ? getSyn() : getHl();
}

@Override
public String getDate() {
    return getFormatedDate();
}

@Override
public int getNewsType() {
    return newSectionType;
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(this.hl);
    dest.writeString(this.imageid);
    dest.writeString(this.syn);
    dest.writeString(this.id);
    dest.writeString(this.dm);
    dest.writeString(this.tn);
    dest.writeString(this.dl);
    dest.writeString(this.sectionHeader);
    dest.writeString(this.upd);
    dest.writeString(this.ud);
    dest.writeInt(this.position);
    dest.writeInt(this.newSectionType);
    dest.writeString(this.dayHeading);
    dest.writeString(this.wu);
}

protected MovieNewsItem(Parcel in) {
    this.hl = in.readString();
    this.imageid = in.readString();
    this.syn = in.readString();
    this.id = in.readString();
    this.dm = in.readString();
    this.tn = in.readString();
    this.dl = in.readString();
    this.sectionHeader = in.readString();
    this.upd = in.readString();
    this.ud = in.readString();
    this.position = in.readInt();
    this.newSectionType = in.readInt();
    this.dayHeading = in.readString();
    this.wu = in.readString();
}

public static final Creator<? extends BaseNewsItem> CREATOR = new Creator<MovieNewsItem>() {
    public MovieNewsItem createFromParcel(Parcel source) {
        return new MovieNewsItem(source);
    }

    public MovieNewsItem[] newArray(int size) {
        return new MovieNewsItem[size];
    }
};

@Override
public boolean equals(Object obj) {
    MovieNewsItem newsItem = this;
    if (obj instanceof MovieNewsItem) {
        MovieNewsItem oldNewsItem = (MovieNewsItem) obj;
        if (oldNewsItem != null &&
                newsItem.id.equals(oldNewsItem.id)) {
            return true;
        }
    }
    return false;
}


}

BaseNewsItem.java:

 public abstract class BaseNewsItem implements NewsItemType {

}


NewsItemType.java:

public interface NewsItemType extends Parcelable {
String getTitle();
String getId();
String getDate();
int getNewsType();
String getDayHeading();
int getValidListPosition();
int getPosition();

void setTitle(String title);
void setId(String id);
void setDate(String date);
void setNewsType(int newsType);
void setDayHeading(String dayHeading);
void setValidListPosition(int listPosition);
void setPosition(int position);


}

最佳答案

您的问题可以通过以下最小示例来重现(用? extends Object替换? extends BaseNewsItem,用Parcelable.Creator替换第二个列表,您会发现逻辑完全相同):

public void test() {
  List<? extends Object> a1 = new ArrayList<> ();
  List<? extends Object> a2 = new ArrayList<> ();
  m(a1, a2); //your compilation error here
}
public <T> void m(List<T> a1, List<T> a2) { }


问题在于两个列表的泛型类型是不相关的:它们都扩展了相同的基类,但这就是我们所了解的全部-例如,a1可能是List<String>,而a2List<Integer>

但是,m方法期望两个泛型类型相同-这不是您要传递的类型。

因此,您需要传递具有相同泛型的列表,例如:

public void test() {
  List<SomeBaseClass> a1 = new ArrayList<> ();
  List<SomeBaseClass> a2 = new ArrayList<> ();
  m(a1, a2); //compiles fine
}
public <T> void m(List<T> a1, List<T> a2) { }

09-30 15:12