我在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)
感谢。
答案 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
。这就是你的例子中正确返回的内容。
这与运行时可用的泛型有关。然后你会受到类型擦除的限制。