2012-09-26 37 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 
}