2012-09-26 31 views
8

这是一个通用的JAVA问题。在Android中,有一个接口Parcelable具有约束访问问题的泛型类

这是official documentation里面的例子:

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静态字段。

一切实际上很简单。现在我想创建一个具有Parcelable类类型泛型类:

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]; 
     } 
    }; 
} 

回答

1

相反的<T extends Parcelable>你需要<T extends ShushContainer<T> & Parcelable>这种方式,你指定TShushContainer这样你就可以访问的方法和变量。

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 您正在尝试静态变量的动态多态性另一个类这是不可能的。

样品例子来展示它是如何失败的

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.

您可以使用反射来检查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()); 

    } 
} 
+0

T是实现Parcelable的另一个类。 –

+0

那么该类如何具有'CREATOR',因为它是在ShushContainer中定义的。这个变量只属于这个类。简单地使用它为什么你需要T.CREATOR只需使用CREATOR –

+0

Nopes ShushContainer实现Parcelable并拥有自己的CREATOR。 T还实现了Parcelable并拥有自己的CREATOR。正是这个创作者,我无法访问。 –

0

这不回答关于如何访问静态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 
}