当前位置: 首页 > 知识库问答 >
问题:

Java -泛型与转换对象

何长恨
2023-03-14

我有一个类<代码>数据

具有泛型属性

private T value;

有没有更好的方法来做以下事情?
即以不同的形式返回泛型类型?

public List<String> getValues() {
    if (value.getClass() != ArrayList.class)
        throw new Exception("Wrong Enum value '%s'", value);
    return (ArrayList<String>) value;
    //ugly
}


public String getStringValue() {
    if (value.getClass() != String.class)
        throw new Exception("Wrong value type '%s'", value);
    return (String) value;
    //ugly
}

public Float getFloatValue() {
    if (value.getClass() != Double.class)
        throw new Exception("Wrong value type '%s'", value);
    return (Float) value;
    //ugly
}

public Long getLongValue() {
    if (value.getClass() != Double.class)
        throw new Exception("Wrong value type '%s'", value);
    return (Long) value;
    //ugly
}
public T getValue() {
    return value;
}

Precision,我使用Gson作为反序列化器,以获得一个列表,每个数据对象可以是异构的< br >也可以注册适配器进行浮点和长整型检测,但它不会更快或更好

编辑:gson无法检索longs:

或者:

 ((Long) d.getValue())

java.lang.Double不能java.lang.Long

Long.parseLong( d.getValue().toString())

java.lang.NumberFormatException: 对于输入字符串:“212231.0”

我试着注册一个长密码

gsonBuilder.registerTypeAdapter(Long.class, new LongAdapter());

private static class LongAdapter implements 
    JsonSerializer<Long>, JsonDeserializer<Long> 
{

    @Override public Long deserialize(
            JsonElement json, 
            Type type,
            JsonDeserializationContext arg2) throws JsonParseException 
    {
        return json.getAsLong();
    }

    @Override
    public JsonElement serialize(Long l, Type arg1,
            JsonSerializationContext arg2) {
        return new JsonPrimitive(new Double(l));
    }
}

Java . lang . illegalargumentexception:无法为java.lang.Long类注册类型适配器

tsOverflow的编辑2:

Data<Float> d1 = new Data<Float>( new Float(6.32));
List<String> l = new ArrayList<String>();
    l.add("fr");
    l.add("it");
    l.add("en");
Data<List<String>> d2 = new Data<List<String>>( l);
Data<Long> d3 = new Data<Long>(new Long(212231));

List<Data> data = new ArrayList<Data>();
    data.add(d1);
    data.add(d2);
    data.add(d3)

new Gson().toJson(data);

共有3个答案

顾嘉良
2023-03-14

您可以直接将类型T用于简单的getter,并将Class.cast用于其他类型:

public class GenericDataTest
{
    private static class DataTest<T>
    {
        private T value;

        public DataTest(T value)
        {
            this.value = value;
        }

        public T getValue()
        {
            return value;
        }

        public Object getValueAsType(Class<?> type)
        {
            return type.cast(value);
        }
    }

    @Test
    public void testGeneric()
    {
        DataTest<String> stringTest = new DataTest<String>("Test");
        Assert.assertEquals("Test", stringTest.getValue());
        Assert.assertEquals("Test", stringTest.getValueAsType(String.class));

        DataTest<Double> doubleTest = new DataTest<Double>(1.0);
        Assert.assertEquals(1.0, doubleTest.getValue());
        Assert.assertEquals(1.0, doubleTest.getValueAsType(Double.class));
    }

    @Test(expected = ClassCastException.class)
    public void testClassCastFailure()
    {
        DataTest<String> stringTest = new DataTest<String>("Test");
        Assert.assertEquals("Test", stringTest.getValueAsType(Float.class));
    }
}
姬衡
2023-03-14

这个设计在我看来很可疑,但为了回答你的实际问题:

Long值的大小写看起来是错误的。您的代码段包含一个c

public Long getLongValue() {
    if (value.getClass() != Double.class) // <<- should be Long.class
        throw new Exception("Wrong value type '%s'", value);
    return (Long) value;
    //ugly
}

因此,应改为:

public Long getLongValue() {
    if (value.getClass() != Long.class)
        throw new Exception("Wrong value type '%s'", value);
    return (Long) value;
    //ugly
}

但是,为了减少代码重复,您可以引入一个通用的helper方法

private T getValue() {
    return value;
}

private <V> V castValue(Class<V> type) {
  if (!type.isInstance(value)) {
    // exception handling
  }
  return type.cast(value);
}

public List<String> getValues() {
    return castValue(ArrayList.class);
}

public String getStringValue() {
    return castValue(String.class);
}

如果您决定采用这种方法,我建议取消数据类的泛化,因为如果实例本身实际上没有约束,那么使用类型参数会很烦人。我会使用Object代替字段类型:

private Object getValue() {
    return value;
}

private <V> V castValue(Class<V> type) {
  if (!type.isInstance(value)) {
    // exception handling
  }
  return type.cast(value);
}

public List<String> getValues() {
    return castValue(ArrayList.class);
}

public String getStringValue() {
    return castValue(String.class);
}
// .. more cases ..
阴飞星
2023-03-14

泛型的重点是不允许一个类同时使用不同的类型。

泛型允许您定义/限制对象实例使用的类型。

泛型背后的想法是消除转换的需要。

在类中使用泛型会导致如下结果:

Data<String> stringData = new Data<String>();
String someString = stringData.getValue();

Data<Long> longData = new Data<Long>();
Long someLong = longData.getValue();

Data<List<String>> listData = new Data<List<String>>();
List<String> someList = listData.getValue();

您应该使用对象和强制转换,或者使用泛型来避免强制转换。

您似乎认为泛型允许在同一实例中进行异构类型化。

这是不对的。

如果你希望一个列表包含混合的类型,那么泛型是不合适的。

而且

要从double创建long,请使用double.longValue()。

若要从double创建浮点型,请使用Double.floatValue()。

我建议阅读文档。

 类似资料:
  • 问题内容: 我有一堂课 具有通用属性 有更好的方法来执行以下操作吗? 即以不同的形式返回泛型? 精度,我使用Gson作为反序列化器,以获取列表,然后每个Data对象都可以是异构的 。还可以注册适配器以进行浮点和长检测,但不会更快或更漂亮 编辑 :gson无法检索多头: 要么: java.lang.Double无法转换为java.lang.Long 要么 java.lang.NumberFormat

  • 问题内容: 我想知道以下两个方法声明之间有什么区别: 有什么可以/可以做的,而不是另一种?我在本网站的其他地方找不到这个问题。 问题答案: 与上下文隔离-没有区别。在和两者上,您只能调用的方法。 但是有上下文-如果您有泛型类: 然后: 与对象相同的代码 两个优点: 无需强制转换(编译器向您隐藏了此内容) 编译有效的时间安全性。如果使用的是版本,则不能确保方法始终返回。如果返回,则在运行时会有一个。

  • 我正试图解决一个泛型问题。我在做一些手工选角,感觉好像我做错了什么。我对使用泛型有点陌生,所以很有可能我在某些方面误用了它们。如能提供指导,将不胜感激。 TLDR: 我有一个带有泛型方法的接口,该泛型方法采用参数。我在一个类中实现了这个接口,但在实现器中,我希望确保是特定类型的(假设,这样我就可以提取一些字段)。我怎么能那样做? 详细信息: 下面有一个接口和一个实现类,其中。 具有以下定义: 而具

  • 我正在创建一个由数组支持的泛型类型堆栈。当我尝试创建泛型类型数组时,Java不允许我这样做。有人告诉我,我必须创建一个类型为Object的数组,并将其转换为泛型类型。我已经将对象数组转换为类型,但如何处理Java不断给我的未检查类型错误? 这就是我目前所处的位置。 更新:我正在创建一个对象数组,然后在方法的末尾将返回类型转换为T类型。

  • 在Java中,大家都知道整数不能转换为字符串,这是编译时的一个错误。 对于这个一般的情况, 我只是不明白为什么在这种情况下,java不能在编译时警告您整数转换为字符串。为什么?据我所知,类型删除是在编译后发生的。 编辑:我只是以为编译器有类型推断才知道T是字符串,这样就不能将Integer强制转换为。但显然没有。

  • 我使用的是Java8。 我最近遇到了这个问题: 这不会抛出java.lang.ClassCastException,为什么呢? 我总是想<code>和<code>System.out。println调用。但当我尝试这样做时,它会像预期的那样抛出异常。