【问题标题】:Java generics and casting to a primitive typeJava 泛型和转换为原始类型
【发布时间】:2014-07-04 12:34:57
【问题描述】:

我目前正在尝试从一本书中学习如何使用泛型。在本章中,它说取一段数据 T 并将其转换为整数。我在 Eclipse 中尝试不同的东西,但它们似乎都不允许这样做。您如何执行以下任务:

LinkedList<T> arr = new LinkedList<T>();

Float fl = 8.74273123948;
arr.add(fl);

然后在另一个班级:

public int findValue(Node node)
{
  T data = node.data;
  int value = Number.valueOf(data);  
  return value;
}

我尝试过使用.valueOf()(int) 以及其他一些东西,但似乎没有什么能满足Java。本书坚持保持方法通用,以防使用浮点数或双精度数而不是字符串或整数。

编辑:对于可能有类似问题的其他人。从所有 cmets 收集到这个问题和被接受的答案:

对数据使用 .toString(),然后根据需要将其解析为所需的任何数据类型。

【问题讨论】:

  • 您正在寻找的东西称为“通用约束”。例如&lt;T implements IntegerConvertible&gt;
  • Node 来自哪里?数据是如何定义的? T 有界吗?
  • 该节点本身在本文中没有定义,但它被描述为“具有带有 Node 的通用列表”。所以,在我有限的理解中,这个节点实际上可以是任何东西。
  • 那么唯一的方法是使用instanceof-operator 来检查泛型是否实现IntegerConvertible 或扩展String 或类似的,如果是则转换它并按照逻辑执行并抛出一个@ 987654329@如果没有。
  • 您的第一个(也是唯一一个)问题是什么“任务”?这完全脱离了任何可能表明本书含义的上下文。这两行 Linked ... 13"); 在这种组合中没有意义。

标签: java generics casting


【解决方案1】:

嗯,这是一本奇怪的书。我会尽量根据我所知道的告诉你它的要点。

泛型是一种构造,它允许您在编译时检查您尝试在特定集合、方法或类中使用的类型是否实际上知道该特定事物运行所必需的功能。

例如,你需要在你的模板中使用调用SearchParameter接口确定的函数,但是你只看到&lt;T&gt;参数作为一个对象。或者,在您的情况下,一个更好的例子可能是一个名为 IntegerConvert 的自定义界面,如下所示:

public interface IntegerConvert
{
    Integer returnAsInteger();
}

你可以有这样的课程:

public class MyData implements IntegerConvert
{
    private String data;

    public MyData(String data)
    {
        this.data = data;
    }

    @Override
    public Integer returnAsInteger()
    {
        return Integer.parseInt(data); //throws ParseException if it doesn't work
    }
}

然后你可以有一个这样的列表:

List<IntegerConvert> listOfConvertibles = new ArrayList<IntegerConvert>();

或者,如果您想在未来更通用,

List<? extends IntegerConvert> listOfConvertibles = new ArrayList<IntegerConvert>();

然后你就可以了

listOfConvertibles.add("25");
listOfConvertibles.add("40");
listOfConvertibles.add("35");
for(IntegerConvert ic : listOfConvertibles)
{
    System.out.println("" + ic.returnAsInteger());
}

虽然这是一个有点过于复杂的例子,但我猜。一个更简单的例子如下:

public class Node<E>
{
    private E data;

    public Node(E e)
    {
        this.data = e;
    }

    public E getData()
    {
        return data;
    }

    public void setData(E e)
    {
        data = e;
    }

    public void print()
    {
        System.out.println(data.toString());
    }
}

public class MyClass
{
    public void doSomething()
    {
        List<Node<Float>> listOfFloatNodes = new ArrayList<Node<Float>>();
        listOfFloatNodes.add(new Node<Float>(new Float(8.7472742f)));
        listOfFloatNodes.add(new Node<Float>(new Float(5.56842742f)));
        listOfFloatNodes.add(new Node<Float>(new Float(6.5467742f)));
        MyOtherClass moc = new MyOtherClass();
        moc.useNodeList(listOfFloatNodes);
    }
}

public class MyOtherClass
{
    public <E> void useNodeList(List<Node<E>> list)
    {
         for(Node<E> node : list)
         {
             printNode(node);
         }
    }

    public <E> void printNode(Node<E> node)
    {
         node.print();
    }
}

public class MainClass
{
    public static void main(String[] args)
    {
        MyClass myClass = new MyClass();
        myClass.doSomething();
    }
}

如果您有任何问题,请发表评论。

【讨论】:

  • 在阅读完您的代码后,我被一个源于您的代码的想法所震惊,并从帮助解决这个问题的每个人那里吸取了一些教训。谢谢大家。
  • 是的,这就是应该如何使用泛型。在 MyOtherClass 中,由于都是实例级别的方法,类型参数可以添加到类本身。
  • 确实如此,但是这样你就不需要在类的实例化时指定类型参数了。在一个特定的用例中,我遇到了一个场景,其中函数之间的模板参数不同,因为有两种方法,其中一个使用另一个接口的扩展版本,因此对函数进行参数化很有帮助但不是整个班级本身。
  • 总的来说,我很高兴它有帮助 :) 泛型可能会令人困惑,我想通了,因为这是将 20 个类的逻辑合并到一个地方的必要条件,呵呵。
【解决方案2】:

尝试观察以下示例:

public static void main(String[] args) {
    test0("13");
    test0(new Integer(13));
    test1();
    System.out.println(findValue(new Node("10")));
}

private static <T> void test0(T a) {
    LinkedList<T> arr = new LinkedList<T>();
    arr.add((T) a);
    System.out.println(arr.getFirst());
}

private static <T> void test1() {
    LinkedList<T> arr = new LinkedList<T>();
    arr.add((T) new Integer(13));
    System.out.println(arr.getFirst());
}

public static <T> int findValue(Node node) {
    T data = (T) node.data;
    int value = Integer.valueOf(data.toString());
    return value;
}

节点在哪里:

    public class Node {

    //this should be private
        public String data;

        public Node(String data) {
            this.data = data;
        }

    //use getter below to access private data
    public String getData() {
            return data;
        }

  }

所有这一切都是可能的,因为允许从已知类型到 T 的未经检查的强制转换(当然有警告)并且编译器相信你进行了强制转换。

【讨论】:

    【解决方案3】:

    尽管密切相关,但并不完全针对该主题进行回答。我遇到了问题,没有找到答案。然后我找到了解决方案并认为我会分享:

    我试图将泛型值转换为原始类型:

    <TYPE> boolean equal(TYPE val, Class<?> type) {
        if (float.class == type) {            
            float val2 = (float) val; // incompatible types: TYPE cannot be converted to float
            float val3 = (float) (Object) val; // works
            ...
    

    长话短说:第一个版本不起作用,第二个版本起作用。很烦人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-03
      • 2010-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多