传递Type参数在Java中具有Type参数

时间:2014-07-01 17:32:36

标签: java android reflection reference

我在Java中使用类型参数度过了不愉快。

我有一个抽象类,它需要一个Type参数作为继承自BaseModel类的类,我会把这个类作为一个Type Parameters传递给另一个内部对象

这是我的班级。

package com.gift.app.fragments;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;

import com.gift.app.client.AsyncCollectionHandler;
import com.gift.app.interfaces.OnFetchCollectionInterface;
import com.gift.app.model.BaseModel;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import java.util.List;

/**
 * Created by andreaascari on 01/07/14.
 */
public abstract class InjectedListFragment<T extends BaseModel> extends InjectedFragment implements OnFetchCollectionInterface<T> {

    private static final String TAG = InjectedListFragment.class.getSimpleName();

    private List<T> mCollection;

    private AsyncCollectionHandler<T> asyncCollectionHandler = new AsyncCollectionHandler<T>("") {
        @Override
        public void onSuccess(List<T> res) {
            mCollection = res;
            fetchCompleted(true);
        }
    };

    @Override
    @SuppressWarnings("unchecked")
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (!mFetchDataIsDisabled)
            fetchData(asyncCollectionHandler);
    }

    public Class<T> getBaseModelExtensionClass() {
        Class klass = ((Object) this).getClass();
        Type type = klass.getGenericSuperclass();
        ParameterizedType paramType = (ParameterizedType) type;
        if (paramType.getActualTypeArguments() != null && paramType.getActualTypeArguments().length > 0) {
            if (BaseModel.class.isAssignableFrom(paramType.getActualTypeArguments()[0].getClass())) {
                return (Class<T>) paramType.getActualTypeArguments()[0];
            }
        }

        return null;
    }

    protected void fetchData() {
        fetchData(asyncCollectionHandler);
    }

    @Override
    protected void canPopulateView() {
        populateView(mCollection);
    }

}

此方法:getBaseModelExtensionClass()返回正确的课程。

这是我的 AsyncCollectionHandler 类。

package com.gift.app.client;

import android.util.Log;

import com.gift.app.BaseActivity;
import com.gift.app.model.BaseModel;
import com.gift.app.model.ModelCollection;
import com.loopj.android.http.AsyncHttpResponseHandler;

import org.apache.http.Header;
import org.apache.http.client.HttpResponseException;
import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.List;

public abstract class AsyncCollectionHandler<T extends BaseModel> extends AsyncHttpResponseHandler {
    private BaseActivity mActivity;
    private String TAG = AsyncCollectionHandler.class.getSimpleName();
    private String wrapProperty;
    private String collection;

    public AsyncCollectionHandler(String colName) {
        wrapProperty = "data";
        collection = colName;
        mActivity = null;
    }

    public AsyncCollectionHandler(String colName, BaseActivity activity) {
        this(colName);
        mActivity = activity;
    }

    @Override
    public void onStart() {
    }


    @SuppressWarnings("unchecked")
    public Class<T> getTypeParameterClass() {
        Class klass = getClass();
        Type type = klass.getGenericSuperclass();
        ParameterizedType paramType = (ParameterizedType) type;
        Log.d(TAG, Arrays.toString(paramType.getActualTypeArguments()));
        return (Class<T>) paramType.getActualTypeArguments()[0];
    }


    public void onSuccess(int i, Header[] headers, byte[] bytes) {
        onSuccess(new String(bytes));
    }

    public final void onSuccess(String json) {
        try {
            JSONObject jsonResponse = new JSONObject(json);
            if (wrapProperty != null) {
                json = jsonResponse.getJSONObject(wrapProperty).toString();
            }
            onSuccess(new ModelCollection<T>(collection).fromJSONList(json, getTypeParameterClass()));

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    public void onFailure(int i, Header[] headers, byte[] bytes, Throwable throwable) {
        onFailure(throwable, new String(bytes));
    }

    public void onFailure(Throwable t, String res) {
        if (res != null)
            Log.i(TAG, res);

        try {
            HttpResponseException httpResponseException = (HttpResponseException) t;
            int statusCode = httpResponseException.getStatusCode();
            switch (statusCode) {
                case 403: {
                    onUnauthorized(t, res);
                }
                default:
                    break;
            }
        } catch (ClassCastException e) {
            e.printStackTrace();
        }

    }

    public void onUnauthorized(Throwable t, String res) {
        if (mActivity != null) {
            mActivity.logout();
        }
    }

    public abstract void onSuccess(List<T> res);
}

但是getTypeParameterClass()会引发错误,导致paramType.getActualTypeArguments()[0]返回 T 本身。

编辑:

完整堆栈跟踪

07-01 20:01:38.076  24877-25218/com.gift.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.gift.app, PID: 24877
    java.lang.ClassCastException: libcore.reflect.TypeVariableImpl cannot be cast to java.lang.Class
            at com.gift.app.client.AsyncCollectionHandler.getTypeParameterClass(AsyncCollectionHandler.java:49)
            at com.gift.app.client.AsyncCollectionHandler.onSuccess(AsyncCollectionHandler.java:63)
            at com.loopj.android.http.AsyncHttpResponseHandler.onSuccess(AsyncHttpResponseHandler.java:117)
            at com.loopj.android.http.AsyncHttpResponseHandler.handleSuccessMessage(AsyncHttpResponseHandler.java:168)
            at com.loopj.android.http.AsyncHttpResponseHandler.handleMessage(AsyncHttpResponseHandler.java:184)
            at com.loopj.android.http.AsyncHttpResponseHandler$1.handleMessage(AsyncHttpResponseHandler.java:84)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5001)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
            at dalvik.system.NativeStart.main(Native Method)

感谢。

1 个答案:

答案 0 :(得分:0)

这个

private AsyncCollectionHandler<T> asyncCollectionHandler = new AsyncCollectionHandler<T>("") {
    @Override
    public void onSuccess(List<T> res) {
        mCollection = res;
        fetchCompleted(true);
    }
};

AsyncCollectionHandler的匿名子类的实例,您已使用声明类&#39;类型参数T作为类型参数。

Class#getGenericSuperclass() javadoc

  

如果超类是参数化类型,则返回Type对象   必须准确反映源中使用的实际类型参数   代码。

因此asyncCollectionHandler变量引用的实例的超类是参数化类型AsyncCollectionHandler,源代码中的实际类型参数(类型参数)是T。这就是你的例子中正确返回的内容。

这与运行时可用的泛型有关。然后你会受到类型擦除的限制。