Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/vim/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是否可以将泛型类打包?_Java_Android_Generics_Parcelable_Parcel - Fatal编程技术网

Java 是否可以将泛型类打包?

Java 是否可以将泛型类打包?,java,android,generics,parcelable,parcel,Java,Android,Generics,Parcelable,Parcel,我正在尝试创建公共类MyClass实现Parcelable。我在实现Parcelable时遇到问题。是否可以创建实现Parcelable的泛型类?(请注意,T是有界的,因此它还必须实现Parcelable) 我遇到了一个问题,即Parcelable接口需要一个static变量:public static final Parcelable.Creator。因此,我无法执行公共静态最终Parcelable.Creator-Creator,因为MyParcelable是非静态的 André在使用泛型的

我正在尝试创建
公共类MyClass实现Parcelable
。我在实现
Parcelable
时遇到问题。是否可以创建实现
Parcelable
的泛型类?(请注意,
T
是有界的,因此它还必须实现
Parcelable

我遇到了一个问题,即Parcelable接口需要一个static变量:
public static final Parcelable.Creator
。因此,我无法执行
公共静态最终Parcelable.Creator-Creator
,因为
MyParcelable
是非静态的


André

在使用泛型的类上实现Parcelable时,我遇到了类似的问题,第一个问题与您遇到的问题相同:

因此,我无法执行公共静态最终Parcelable.Creator>Creator,因为MyParcelable是非静态的

第二种方法是读入需要访问
ClassLoader
的可包裹对象,该对象由于以下原因无法从
T
获取

下面的类是我在生产中使用的一个类的改编,它克服了这两个问题。注意:我没有专门测试这个类,所以如果您有任何问题,请告诉我

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

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
}
public类TestModel实现可包裹{
私人清单项目;
私有字符串字段;
公共物品清单(){
退货项目;
}
公共无效集合项(列出新值){
项目=新值;
}
公共字符串someField(){
返回someField;
}
public void setSomeField(字符串newValue){
someField=newValue;
}
//地区:可包裹实施
公共测试模型(地块中){
someField=in.readString();
int size=in.readInt();
如果(大小==0){
items=null;
}
否则{
.readSerializable()中的类类型=(类);
items=新阵列列表(大小);
在.readList中(items,键入.getClassLoader());
}
}
@凌驾
公共int描述内容(){
返回0;
}
@凌驾
公共无效写入包裹(包裹目的地,内部标志){
目的地写入限制(someField);
if(items==null | | items.size()==0)
目的写入(0);
否则{
dest.writeInt(items.size());
最终类objectsType=items.get(0.getClass();
目标可写变量(objectsType);
目的书面清单(项目);
}
}
public static final Parcelable.Creator=新建Parcelable.Creator(){
公共测试模型createFromParcel(地块中){
返回新的TestModel(in);
}
公共测试模型[]新数组(整数大小){
返回新的TestModel[大小];
}
};
//端区
}

是的,你可以。在构建子类对象的过程中,您只需要存储类名或类加载器,然后就可以在parcelable的读/写操作中传递它

逐步说明:

步骤1。存储从泛型类扩展而来的类名,如下所示:

public abstract class GenericClass<T> implements Parcelable {
    private String className;
public class MyClass extends GenericClass<MyClass> {

    public MyClass () {
        super();
        setClassName(MyClass.class.getName()); // Generic class setter method
    }
public abstract class GenericClass<T> implements Parcelable {
    private String className;
    T myGenericObject;

    protected MyClass (Parcel in) {
        super(in);
        this.className = in.readString();
        ClassLoader classLoader;
        try {
            classLoader = Class.forName(this.className).getClassLoader();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        myGenericObject = in.readParcelable(classLoader);
        //... Other class members can go here
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeString(className);
        //... Other class members can go here
    }
公共抽象类GenericClass实现了Parcelable{
私有字符串类名;
步骤2。任何从泛型类扩展而来的类都必须在其构造过程中指定类名,如下所示:

public abstract class GenericClass<T> implements Parcelable {
    private String className;
public class MyClass extends GenericClass<MyClass> {

    public MyClass () {
        super();
        setClassName(MyClass.class.getName()); // Generic class setter method
    }
public abstract class GenericClass<T> implements Parcelable {
    private String className;
    T myGenericObject;

    protected MyClass (Parcel in) {
        super(in);
        this.className = in.readString();
        ClassLoader classLoader;
        try {
            classLoader = Class.forName(this.className).getClassLoader();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        myGenericObject = in.readParcelable(classLoader);
        //... Other class members can go here
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeString(className);
        //... Other class members can go here
    }
公共类MyClass扩展了GenericClass{
公共MyClass(){
超级();
setClassName(MyClass.class.getName());//泛型类设置器方法
}
步骤3。在泛型类中,您可以将类名读/写到getClassLoader(),如下所示:

public abstract class GenericClass<T> implements Parcelable {
    private String className;
public class MyClass extends GenericClass<MyClass> {

    public MyClass () {
        super();
        setClassName(MyClass.class.getName()); // Generic class setter method
    }
public abstract class GenericClass<T> implements Parcelable {
    private String className;
    T myGenericObject;

    protected MyClass (Parcel in) {
        super(in);
        this.className = in.readString();
        ClassLoader classLoader;
        try {
            classLoader = Class.forName(this.className).getClassLoader();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        myGenericObject = in.readParcelable(classLoader);
        //... Other class members can go here
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeString(className);
        //... Other class members can go here
    }
公共抽象类GenericClass实现了Parcelable{
私有字符串类名;
T myGenericObject;
受保护的MyClass(包裹中){
超级(in),;
this.className=in.readString();
类加载器类加载器;
试一试{
classLoader=Class.forName(this.className).getClassLoader();
}catch(classnotfounde异常){
e、 printStackTrace();
}
myGenericObject=in.readParcelable(类加载器);
//……其他班级成员可以到这里来
}
@凌驾
公共无效写入包裹(包裹目的地,内部标志){
超级可写包裹(目的地、旗帜);
目的写入目录(类名);
//……其他班级成员可以到这里来
}

}

将通用数据成员类名写入地块,然后将其读回以创建其类加载器。例如

public class MyClass<T> implements Parcelable {
    T data;

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(data.getClass().getName());
        dest.writeParcelable((Parcelable) data, 0);
    }

    private MyClass(Parcel in) {
        final String className = in.readString();
        try {
            data = in.readParcelable(Class.forName(className).getClassLoader());
        } catch (ClassNotFoundException e) {
            Log.e("readParcelable", className, e);
        }
    }
公共类MyClass实现了可包裹{
T数据;
@凌驾
公共无效写入包裹(包裹目的地,内部标志){
dest.writeString(data.getClass().getName());
目的地可写可强制((可包裹)数据,0);
}
私人MyClass(包裹内){
最终字符串className=in.readString();
试一试{
data=in.readParcelable(Class.forName(className).getClassLoader());
}catch(classnotfounde异常){
Log.e(“readParcelable”,类名,e);
}
}

基于上述答案,我们已经为此创建了扩展函数

fun <T : Parcelable> Parcel.writeGenericParcelable(data: T, flags: Int) {
    writeString(data::class.java.name)
    writeParcelable(data, flags)
}

fun <T : Parcelable> Parcel.readGenericParcelable(): T {
  val className = readString()!!
  val classNameLoader = Class.forName(className).classLoader
  return readParcelable(classNameLoader)!!
}
fun-Parcel.writeGenericParcelable(数据:T,标志:Int){
writeString(数据::class.java.name)
可写可强制(数据、标志)
}
有趣的包裹。readGenericParcelable():T{
val className=readString()!!
val classNameLoader=Class.forName(className).classLoader
返回readParcelable(classNameLoader)!!
}

Related if not replicate:谢谢。问题是一样的。虽然没有提供有效的解决方案,但我不能在该帖子上发表评论,因为我没有足够的“声誉”!我浏览了你的其他问题,并对它们进行了评价,认为它们写得很好。作为一个副作用,你现在应该有足够的代表发表评论。非常感谢Paul。这真的很有帮助!!对于其他人来说,我是如何做到的:
protectedothermodel(packetin){mTestModel=in.readParcelable(TestModel.class.getClassLoader());}
只是想知道为什么要同时调用writeList(items)和遍历调用item.writeToPa的列表