Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.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_Generics_Types - Fatal编程技术网

java泛型:运行时类型检查以确定策略

java泛型:运行时类型检查以确定策略,java,generics,types,Java,Generics,Types,如何根据泛型类型选择不同的方法 简单地说,我有一个用泛型类型参数化的类,我必须根据T类型选择正确的PreparedStatement setter: Class CustomFieldsTypeManager<T> { ArrayList<T> data; public void setUpStatement(PreparedStatement st){ ... if ( **T==String** ){ st.se

如何根据泛型类型选择不同的方法

简单地说,我有一个用泛型类型参数化的类,我必须根据T类型选择正确的PreparedStatement setter:

Class CustomFieldsTypeManager<T> {
   ArrayList<T> data;

   public void setUpStatement(PreparedStatement st){
      ...
      if ( **T==String** ){
         st.setString(index, (String) data<T>.get(dt_index);
      } else if ( **T==Integer** ){
         st.setInt(index, (String) data<T>.get(dt_index);
      }
      ...
   }
}
Class CustomFieldsTypeManager{
阵列列表数据;
公开声明(已编制声明st){
...
如果(**T==字符串**){
st.setString(索引,(字符串)data.get(dt_索引);
}如果(**T==整数**),则为else{
st.setInt(index,(String)data.get(dt_index);
}
...
}
}

您正在查找的
实例

if ( data.get(dt_index) instanceof String ) {
    //...
}

您正在查找
实例的

if ( data.get(dt_index) instanceof String ) {
    //...
}

由于类型擦除,泛型信息在运行时丢失。您应该尝试以不同的方式利用参数多态性,提供类的专门化:

class CustomFieldsTypeManager<T> {
   ArrayList<T> data;

   abstract void setUpStatement(PreparedStatement st);
}

class StringCustomFieldsTypeManager extends CustomFieldsTypeManager<String> {
   void setUpStatement(PreparedStatement st) {
     st.setString(index, data.get(dt_index)); // data it's already an ArrayList<String>
   }
}
class CustomFieldsTypeManager{
阵列列表数据;
摘要无效报表(已编制报表st);
}
类StringCustomFieldsTypeManager扩展了CustomFieldsTypeManager{
作废报表(已编制报表st){
st.setString(index,data.get(dt_index));//data它已经是一个ArrayList了
}
}

还有一些方法可以在运行时检查它,但这种方法会破坏泛型继承的优点,即使它们与此解决方案一样安全(必须正确编写).

由于类型擦除,泛型信息在运行时丢失。您应该尝试以不同的方式利用参数多态性,方法是提供类的专门化:

class CustomFieldsTypeManager<T> {
   ArrayList<T> data;

   abstract void setUpStatement(PreparedStatement st);
}

class StringCustomFieldsTypeManager extends CustomFieldsTypeManager<String> {
   void setUpStatement(PreparedStatement st) {
     st.setString(index, data.get(dt_index)); // data it's already an ArrayList<String>
   }
}
class CustomFieldsTypeManager{
阵列列表数据;
摘要无效报表(已编制报表st);
}
类StringCustomFieldsTypeManager扩展了CustomFieldsTypeManager{
作废报表(已编制报表st){
st.setString(index,data.get(dt_index));//data它已经是一个ArrayList了
}
}

还有一些方法可以在运行时检查它,但这有点挫败了泛型继承的优点,即使它们与此解决方案一样安全(必须正确编写)。

您不能。但您可以做的是:

class CustomFieldsTypeManager<T> {
    private Class<T> type;
    public CustomFieldsTypeManager(Class<T> type) {
        this.type = type;
    }
}
class CustomFieldsTypeManager{
私人阶级类型;
公共CustomFieldsTypeManager(类类型){
this.type=type;
}
}
然后:

CustomFieldsTypeManager m=新的CustomFieldsTypeManager(String.class);
最后:

public void setUpStatement(PreparedStatement st) {
    if (type.equals(String.class)){
        st.setString(index, (String) data<T>.get(dt_index);
    } else if (type.equals(Integer.class)){
        st.setInt(index, (String) data<T>.get(dt_index);
    }
}
public void语句(PreparedStatement st){
if(type.equals(String.class)){
st.setString(索引,(字符串)data.get(dt_索引);
}else if(type.equals(Integer.class)){
st.setInt(index,(String)data.get(dt_index);
}
}

或者,只需使用
PreparedStatement#setObject
方法,而不是您正在使用的方法。

您不能。但您可以做的是:

class CustomFieldsTypeManager<T> {
    private Class<T> type;
    public CustomFieldsTypeManager(Class<T> type) {
        this.type = type;
    }
}
class CustomFieldsTypeManager{
私人阶级类型;
公共CustomFieldsTypeManager(类类型){
this.type=type;
}
}
然后:

CustomFieldsTypeManager m=新的CustomFieldsTypeManager(String.class);
最后:

public void setUpStatement(PreparedStatement st) {
    if (type.equals(String.class)){
        st.setString(index, (String) data<T>.get(dt_index);
    } else if (type.equals(Integer.class)){
        st.setInt(index, (String) data<T>.get(dt_index);
    }
}
public void语句(PreparedStatement st){
if(type.equals(String.class)){
st.setString(索引,(字符串)data.get(dt_索引);
}else if(type.equals(Integer.class)){
st.setInt(index,(String)data.get(dt_index);
}
}

或者,只需使用
PreparedStatement#setObject
方法,而不是您正在使用的方法。

@user2224731请单击代表下方的复选框,将帖子标记为答案。唯一需要注意的是“非对象类型”(如int)其属于对象,因此对Integer的类型检查失败。解决方案是强制强制转换为getter(data.get)。[也许此信息可以在将来帮助有相同问题的人]@user2224731 A
List
不支持
int
但支持
Integer
。是的,我知道,GenericsGet-it不支持基元类型!错误取决于此字段值。添加((t)new Object());我用来初始化一个空列表。这是因为我不知道如何创建一个新的t的泛型实例。它可以工作,但当我从数组中得到一些东西时,我需要强制转换为t。@user2224731请单击代表下面的复选框将文章标记为答案。唯一的警告是“非对象类型”(如int)其属于对象,因此对Integer的类型检查失败。解决方案是强制强制转换为getter(data.get)。[也许此信息可以在将来帮助有相同问题的人]@user2224731 A
List
不支持
int
但支持
Integer
。是的,我知道,GenericsGet-it不支持基元类型!错误取决于此字段值。添加((t)new Object());我用来初始化一个空列表。这是因为我不知道如何创建一个新的t的泛型实例。它可以工作,但当我从数组中得到一些东西时,我需要强制转换为t。天哪。我没有注意到有这样一个方法……我已经用实例of解决了……但无论如何,我会记住未来的,天哪。我没有注意到注意到有这样一种方法…我已经用instanceof解决了…但是无论如何我会记住未来我已经用instanceof解决了,无论如何谢谢你。我喜欢你的设计解决方案。非常有趣。我已经用instanceof解决了,无论如何谢谢你。我喜欢你的设计解决方案。非常有趣