首页 > 解决方案 > 转换 Integer -> Object 和后来的 Object -> Integer

问题描述

下面是 AVL 树实现的代码片段。过去它工作得很好,但现在它不再工作了。原因似乎是将 Object 转换为 Integer。

因此 Avl 结构将 Object 作为数据处理,而用户(在本例中为 main() )进行转换。我想要实现的是具有可比较对象的通用 AVL 树。实际上,我将对象与一个键一起插入,以便能够区分要排序的内容。它们在内部被放置在一个名为 KeyData 的本地类中。

这是代码:

  // private stuff above - not interesting for problem

  // Public AVL tree methods

  public void insert(Object thedata, String thekey) {
    internal_insert(new KeyData(thedata, thekey));
  }

  public Object find(String key) {
    Object ret = null;
    KeyData x = new KeyData(null, key);
    if(data != null) {
      if(x.compareTo(data) == 0)
    ret = data;
      else if(x.compareTo(data) < 0) {
    if(left != null)
      ret = left.find(key);
      } else {
    if(right != null)
      ret = right.find(key);
      }
    }
    return ret;
  }

  public Object[] inorder() {
    Vector<Object> v = new Vector<Object>();
    iinorder(v);
    return v.toArray();
  }

  public static void main(String[] args) {
    Avl test = new Avl();
    test.insert(Integer.valueOf(1090), "1");
    test.insert(Integer.valueOf(343452), "2");
    test.insert(Integer.valueOf(3345), "3");
    //Object t2 = test.find("2");
    Object lookfor = test.find("2");
    Integer t2 = (Integer) lookfor; // Line 164
    System.out.println("Got: " + t2.toString());
  }

结果如下:

$ java Avl
Exception in thread "main" java.lang.ClassCastException: 
    class Avl$KeyData cannot be cast to class java.lang.Integer (Avl$KeyData is in unnamed module of loader 'app'; java.lang.Integer is in module java.base of loader 'bootstrap')
    at Avl.main(Avl.java:164)

……那是什么故事?

标签: javacasting

解决方案


……那是什么故事?

简短的版本是您的find方法不返回Integer值。因此,您不能其转换为Integer.

过去它工作得很好,但现在它不再工作了。

好吧,从那时到现在,您的代码中一定发生了重大变化。(提示:Java 语言或其实现并没有以导致这种情况的方式发生变化!)

所以让我们看看你的find方法。

public Object find(String key) {
    Object ret = null;
    KeyData x = new KeyData(null, key);
    if (data != null) {
        if (x.compareTo(data) == 0)
            ret = data;
        else if (x.compareTo(data) < 0) {
            if (left != null)
                ret = left.find(key);
        } else {
            if (right != null)
                ret = right.find(key);
        }
    }
    return ret;
}

第一个观察是你的方法的原始缩进是一团糟。糟糕的缩进让你的代码很难让每个人都阅读......和理解。我已经修好了。

所以该find方法是递归地搜索一棵树,并在找到匹配项时。它返回任何data内容。我看不到该Data字段的声明,但有证据表明它是Avl.KeyData. (这是有道理的......因为您将data其与x哪个KeyData实例进行比较。)

无论如何,这解释了为什么结果不是Integer.

你还没有向我们展示这个KeyData类,但我猜它有一个value字段是 / 应该是一个Integer. 这就是你应该返回的。找到KeyData的对象的值字段的内容。

但这里最大的问题是你使用Object. 正如@NomadMaker 评论的那样,这应该是一个具有类型参数的泛型类型,该类型参数将是树中值的类型。然后您不必在main... 中使用类型转换,编译器会告诉您find返回 aKeyData<V>而不是 a是不正确的V

(您的实施还有一些其他问题......但这不是“诊所”。)


推荐阅读