通用类与约束的访问问题 [英] Generic Class with Constraint access issue

查看:128
本文介绍了通用类与约束的访问问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个一般的Java问题。在Android中,有一个接口<一href="http://developer.android.com/reference/android/os/Parcelable.html"><$c$c>Parcelable:

这是官方文档里面一个例子:

 公共类MyParcelable实现Parcelable {
     私人诠释MDATA;

     公众诠释describeContents(){
         返回0;
     }

     公共无效writeToParcel(包裹出来,诠释标志){
         out.writeInt(MDATA);
     }

     公共静态最终Parcelable.Creator&LT; MyParcelable&GT; CREATOR
             =新Parcelable.Creator&LT; MyParcelable&GT;(){
         公共MyParcelable createFromParcel(包裹中){
             返回新MyParcelable(中);
         }

         公共MyParcelable [] newArray(INT尺寸){
             返回新MyParcelable【尺寸】;
         }
     };

     私人MyParcelable(包裹中){
         MDATA = in.readInt();
     }
 }
 

我们正在实现2功能所需 describeContents() writeToParcel

(问题) 除了他们,我们也需要落实 Parcelable.Creator&LT; T&GT; 接口配置为静态,名为CREATOR

一切实际上是直线前进。现在,我想创建一个通用类,有一个Parcelable类类型:

 公共类ShushContainer&LT;吨延伸Parcelable&GT;实现Parcelable
 

我能够实现Parcelable。我可以调用 T writeToParcel 功能。但是,我无法访问静态CREATOR领域。

 公共类ShushContainer&LT;吨延伸Parcelable&GT;实现Parcelable {
    矢量&lt; T&GT;项目;
    字符串someField;

    @覆盖
    公众诠释describeContents(){
        返回0;
    }

    @覆盖
    公共无效writeToParcel(包裹DEST,INT标志){
        dest.writeString(someField);
        dest.writeInt(items.size());
        的for(int i = 0; I&LT; items.size();我++)
            items.get(我).writeToParcel(DEST,旗);
    }

    公共ShushContainer(包裹中){
        someField = in.readString();
        INT大小= in.readInt();
        的for(int i = 0; I&LT;大小;我++)
            //这不起作用
            items.add(T.CREATOR.createFromParcel(在));
    }

    公共静态最终Parcelable.Creator&LT; ShushContainer&GT; CREATOR =新Parcelable.Creator&LT; ShushContainer&GT;(){
        公共ShushContainer createFromParcel(包裹中){
            返回新ShushContainer(中);
        }

        公共ShushContainer [] newArray(INT尺寸){
            返回新ShushContainer【尺寸】;
        }
    };
}
 

解决方案

而不是&LT的;吨延伸Parcelable&GT; 需要&LT;吨延伸ShushContainer&LT; T&GT; &放大器; Parcelable&GT; 这样指定 T ShushContainer 这样你就可以访问的方法和变量。

 公共类ShushContainer&LT;吨延伸ShushContainer&LT; T&GT; &放大器; Parcelable&GT;
实现Parcelable
 

下面是使用的例子序列化

 类样品&LT;吨延伸采样&LT; T&GT; &放大器;序列化&GT;实现Serializable {

  公共静态INT CONST = 0;

   公共无效美孚()
   {
     T.CONST = 5;
   }
}
 

更新

如果我理解正确threre是实现其他类 Parcelable 具有 CREATOR 您正在尝试为静态变量,是不可能的动态多态性。

样品为例,说明​​它是如何失败

 公共类基地{
    公共静态诠释计数= 10;
}

公共类儿童扩展基地{
    公共静态诠释计数= 20;
}


类样品&LT;吨延伸基地&GT; {
    T(T)= NULL;
    公共无效printCount(){
        的System.out.println(T.count);
    }
    公共样品(T(T)){
        this.t = T;
    }

    公共静态无效的主要(字串[] args){
        样品&LT;儿童&GT;样品=新采样&LT;儿童&GT;(新的儿童());
        样品&LT;基地&GT; SAMPLE1 =新采样&LT;基地&GT;(新基地());
        sample.printCount();打印为10 //子值
        sample1.printCount(); //相同的父值打印为10
    }

}
 

该计划失败,因为静态字段绑定到类,而不是实例,以便有两个独立的计数之一基本和一个用于孩子如果你访问基础值那么它将永远是10。

您可以使用反射来检查是否 CREATOR 字段present和访问it.Which将不可能没有对象或类对象。

或者你可以这样做下面使用<一个href="http://www.java2s.com/Open-Source/Android/UnTagged/smartshop-project/com/google/gson/reflect/TypeToken.java.htm"相对=nofollow> TypeToken

 类样品&LT;吨延伸序列化&GT;实现Serializable {

    公众诠释ABC = 0;
    公共无效美孚(){
    }
    公共静态无效的主要(字串[] args)抛出SecurityException异常,NoSuchFieldException {
        TypeToken&lt;样品&LT;整数GT;&GT;令牌=新TypeToken&lt;样品&LT;整数GT;&GT;(){
        };
        类&LT;&GT; T = token.getRawType();
        场场= t.getDeclaredField(ABC);
        field.setAccessible(真正的);
        的System.out.println(field.getName());

    }
}
 

This a general JAVA question. In android, there is an interface Parcelable:

This is an example inside the 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();
     }
 }

We are required to implement the 2 functions describeContents() and writeToParcel.

(problem) Besides them, we are also required to implement the Parcelable.Creator<T> interface as a static field called CREATOR.

Everything is actually straight forward. Now I want to create a Generic Class that has a Parcelable Class Type:

public class ShushContainer<T extends Parcelable> implements Parcelable

I am able to implement Parcelable. I can call the T's writeToParcel function. However, I am unable to access the static CREATOR field.

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

解决方案

Instead of <T extends Parcelable> you need <T extends ShushContainer<T> & Parcelable> this way you specify that T is ShushContainer so you can access is methods and variables.

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

Here is the example using Serializable

class Sample<T extends Sample<T> & Serializable> implements Serializable {

  public static int CONST = 0;

   public void foo()
   {
     T.CONST = 5;
   }
}

Update

If I understand correctly threre is another class which implements Parcelable which has CREATOR You are trying dynamic polymorphism for Static variables which is not possible.

Sample example to show how it fails

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
    }

}

This program fails because static fields are bound to Class rather than instance so there are two separate count one for Base and one for Child if you access value of Base then it will always be 10.

You can use reflection to check whether CREATOR field is present and access it.Which will not be possible without object or class object.

Or You can do something like below using 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());

    }
}

这篇关于通用类与约束的访问问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆