我是java泛型的新手,下面的代码为我将泛型类作为参数传递给方法造成了混乱。 我创建了一个android项目,我用Volley库来处理服务器调用.Below是代码
Advanced Connection Util:此类返回JacksonRequest对象
public class AdvancedConnectionUtil<T> {
private String requestType;
private ServerListener listener;
public AdvancedConnectionUtil(String requestType , ServerListener<T> listener){
this.listener = listener;
this.requestType = requestType;
}
public JacksonRequest getRequest(){
//This gives compile error while while passing DataList.class in the argument
return new JacksonRequest<T>(Request.Method.GET, HttpRequestConstant.JACKSON_FETCH, null ,DataList.class, new Response.Listener<T>() {
@Override
public void onResponse(T response) {
listener.onDataReceived(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
listener.onErrorReceived(error.getMessage());
}
});
}
public interface ServerListener<T> {
public void onDataReceived(T data);
public void onErrorReceived(String errorMsg);
}
}
自定义JacksonRequest类:此类处理服务器调用和成功回调
public class JacksonRequest<T> extends JsonRequest<T> {
private Class<T> responseType;
/**
* Creates a new request.
* @param method the HTTP method to use
* @param url URL to fetch the JSON from
* @param requestData A {@link Object} to post and convert into json as the request. Null is allowed and indicates no parameters will be posted along with request.
* @param responseType
* @param listener Listener to receive the JSON response
* @param errorListener Error listener, or null to ignore errors.
*/
public JacksonRequest(int method, String url, Object requestData, Class<T> responseType, Response.Listener<T> listener, Response.ErrorListener errorListener) {
super(method, url, (requestData == null) ? null : Mapper.string(requestData), listener, errorListener);
this.responseType = responseType;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return super.getHeaders();
}
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(Mapper.objectOrThrow(json, responseType), HttpHeaderParser.parseCacheHeaders(response));
} catch (Exception e) {
return Response.error(new ParseError(e));
}
}
}
这是我的活动类,它创建一个请求并将其传递给其他方法以进行服务器调用
public class CustomJacksonRequestActivity extends SuperActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
showProgressBar();
JacksonRequest jacksonRequest = new AdvancedConnectionUtil<DataList>(null, httpListener).getRequest();
//This commented code works fine when i create a request this way
/* JacksonRequest<DataList> jacksonRequest = new JacksonRequest<DataList>(Request.Method.GET, HttpRequestConstant.JACKSON_FETCH, null, DataList.class, new Response.Listener<DataList>() {
@Override
public void onResponse(DataList response) {
hideProgressBar();
Log.e("ANSH", "onResponse : " + response.getPicture());
// fillListWithIndex(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
hideProgressBar();
Log.e("ANSH", "onErrorResponse : " + error.getLocalizedMessage());
}
});*/
onExecute(jacksonRequest);
}
@Override
protected void internetAvailable() {
}
@Override
public void setTitle(CharSequence title) {
super.setTitle("CustomJacksonActivity");
}
private AdvancedConnectionUtil.ServerListener httpListener = new AdvancedConnectionUtil.ServerListener<DataList>() {
@Override
public void onDataReceived(DataList data) {
Log.e("ANSH", "onResponse : " + data.getPicture());
}
@Override
public void onErrorReceived(String errorMsg) {
Log.e("ANSH", "onResponse : " + errorMsg);
}
};
现在的问题是我无法将DataList.class(这是响应模型类)作为一个参数传递给AdvancedConnectionUtil类的getRequest方法中的JacksonRequest类的构造函数,尽管我能够做到这一点当我是在活动中创建请求对象(请参阅活动中的注释代码)。 如何将DataList.class传递给JacsonRequest的构造函数?
更新后的代码现在位于git hub中 github link to the project
答案 0 :(得分:0)
你的代码有点令人困惑(你可以用一个更简单的例子),但我会给它一个镜头......
JacksonRequest
类采用一个泛型类型参数 <T>
,第四个构造函数参数的类型引用此类型:, Class<T> responseType,
。这意味着当实例化JacksonRequest
的实例(T为实数类型)时,传递的第4个参数必须保证为T.class
类型。
当你调用构造函数时......
return new JacksonRequest<T>(Request.Method.GET, blah, null ,DataList.class, ...
...您使用泛型类型参数 <T>
调用它。编译器必须始终能够将泛型类型参数与泛型类型参数匹配,但是使用第4个参数,您要求它将T
与DataClass
匹配。由于编译器不知道T
是什么(或者更准确地说,它不能保证在实例化时T
实际上是DataClass
),它会产生错误。
一般来说,您不能混合泛型类型参数和实际类型值 - 您必须始终选择其中一个。有些选项允许您指定泛型类型参数将从类派生或实现接口(<T super DataClass>
或<T extends DataClass>
,但在此处解释有点多。
答案 1 :(得分:0)
您的代码存在的问题是:
您的JacksonRequest<T>
被声明为listener
, 必须 参数设置与responseType
但是对于AdvancedConnectionUtil<T>.getRequest(...)
,无法保证创建的JacksonRequest符合上述要求。因为您总是可以编写如下代码:
new AdvancedConnectionUtil<String> (null, httpListener).getRequest();
因此,您传递到JacksonRequest
构造函数的参数将是DataList.class
(类型为Class<DataList>
)和listener
类型为Listener<String>
可悲的是,Java中没有办法T.class
,尽管这确实感觉就像你需要的那样。通常在这种情况下,我们将AdvancedConnectionUtil声明为:
class AdvancedConnectionUtil<T> {
private final Class<T> responseType;
private final ServerListener<T> serverListener;
private final String requestType;
public AdvancedConnectionUtil (String requestType , Class<T> responseType, ServerListener<T> listener) {
this.requestType = requestType;
this.responseType = responseType;
this.serverListener = listener;
}
public JacksonRequest<T> getRequest(){
return new JacksonRequest<T>(0, "", null ,responseType, new Response.Listener<T>(){
...
}
}
您需要将Class<T>
的responseType传递给AdvancedConnectionUtil
并将其保留为成员字段。这样,AdvancedConnectionUtil
实例在创建时严格限制为提供与特定响应类型相关的JacksonRequest
。
理论上,您可以将getRequest方法声明为getRequest(Class<T> responseType)
。但是你的AdvancedConnectionUtil似乎没有从中获得任何东西