具有约束访问问题的generics类

这是一个普通的JAVA问题。 在android中,有一个接口Parcelable

这是官方文档中的一个例子:

  public class MyParcelable implements Parcelable { private int mData; public int describeContents() { return 0; } public void writeToParcel(Parcel out, int flags) { out.writeInt(mData); } public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() { public MyParcelable createFromParcel(Parcel in) { return new MyParcelable(in); } public MyParcelable[] newArray(int size) { return new MyParcelable[size]; } }; private MyParcelable(Parcel in) { mData = in.readInt(); } } 

我们需要实现describeContents()writeToParcel两个函数。

(问题)除此之外,我们还需要将Parcelable.Creator<T>接口实现为一个名为CREATOR的静态字段。

一切都很简单。 现在我想创build一个具有Parcelable Class Type的generics类:

 public class ShushContainer<T extends Parcelable> implements Parcelable 

我能够实现Parcelable。 我可以调用TwriteToParcel函数。 但是,我无法访问静态CREATOR字段。

 public class ShushContainer<T extends Parcelable> implements Parcelable { Vector<T> items; String someField; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(someField); dest.writeInt(items.size()); for(int i=0;i<items.size();i++) items.get(i).writeToParcel(dest, flags); } public ShushContainer(Parcel in) { someField = in.readString(); int size = in.readInt(); for(int i=0;i<size;i++) //this does not work items.add(T.CREATOR.createFromParcel(in)); } public static final Parcelable.Creator<ShushContainer> CREATOR = new Parcelable.Creator<ShushContainer>() { public ShushContainer createFromParcel(Parcel in) { return new ShushContainer(in); } public ShushContainer[] newArray(int size) { return new ShushContainer[size]; } }; } 

Related of "具有约束访问问题的generics类"

您需要<T extends ShushContainer<T> & Parcelable> <T extends Parcelable>代替<T extends ShushContainer<T> & Parcelable>您可以指定TShushContainer因此您可以访问方法和variables。

 public class ShushContainer<T extends ShushContainer<T> & Parcelable> implements Parcelable 

这里是使用Serializable的例子

 class Sample<T extends Sample<T> & Serializable> implements Serializable { public static int CONST = 0; public void foo() { T.CONST = 5; } } 

更新

如果我理解正确threre是另一个类实现Parcelable哪个具有CREATOR你正在尝试dynamic多态的静态variables是不可能的。

示例示例,以显示它如何失败

 public class Base { public static int count = 10; } public class Child extends Base { public static int count = 20; } class Sample<T extends Base> { T t = null; public void printCount() { System.out.println(T.count); } public Sample(T t) { this.t = t; } public static void main(String[] args) { Sample<Child> sample = new Sample<Child>(new Child()); Sample<Base> sample1 = new Sample<Base>(new Base()); sample.printCount();//Child value printed as 10 sample1.printCount();//Same for parent value printed as 10 } } 

这个程序失败,因为静态字段绑定到类而不是实例,所以有两个单独的count一个Base和一个Child如果你访问价值的Base那么它将永远是10。

您可以使用reflection来检查CREATOR字段是否存在并访问它。如果没有对象或类对象,那么这将是不可能的。

或者你可以使用TypeToken做下面的事情

 class Sample<T extends Serializable> implements Serializable { public int abc = 0; public void foo() { } public static void main(String[] args) throws SecurityException, NoSuchFieldException { TypeToken<Sample<Integer>> token = new TypeToken<Sample<Integer>>() { }; Class<?> t = token.getRawType(); Field field = t.getDeclaredField("abc"); field.setAccessible(true); System.out.println(field.getName()); } } 

这不会回答你如何访问静态CREATOR属性的问题,但是你不需要访问这个属性实现Parcelable。 看下面的例子:

 public class TestModel<T extends Parcelable> implements Parcelable { private List<T> items; private String someField; public List<T> items() { return items; } public void setItems(List<T> newValue) { items = newValue; } public String someField() { return someField; } public void setSomeField(String newValue) { someField = newValue; } //region: Parcelable implementation public TestModel(Parcel in) { someField = in.readString(); int size = in.readInt(); if (size == 0) { items = null; } else { Class<?> type = (Class<?>) in.readSerializable(); items = new ArrayList<>(size); in.readList(items, type.getClassLoader()); } } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(someField); if (items == null || items.size() == 0) dest.writeInt(0); else { dest.writeInt(items.size()); final Class<?> objectsType = items.get(0).getClass(); dest.writeSerializable(objectsType); dest.writeList(items); } dest.writeInt(items.size()); for(int i=0;i<items.size();i++) items.get(i).writeToParcel(dest, flags); } public static final Parcelable.Creator<TestModel> CREATOR = new Parcelable.Creator<TestModel>() { public TestModel createFromParcel(Parcel in) { return new TestModel(in); } public TestModel[] newArray(int size) { return new TestModel[size]; } }; //endregion }