【问题标题】:Is this generic autoboxing?这是通用的自动装箱吗?
【发布时间】:2010-07-10 16:08:51
【问题描述】:

在不使用“this.getAnything(int flag)”等常用符号的情况下分配值

private <T> T getAnything(int flag) {
    Object o = null;
    if (flag==0)
        o=new String("NewString");
    else if (flag==1)
        o=new Double(0D);
    return (T)o;
}


private void someMethod() {
    String s = getAnything(0);
    Double d = getAnything(1);
}

在过去,仅方法上的返回对象和接收类型上的简单强制转换就足够了,因此由于接收器对象上缺少通用符号,因此编写起来更加相似和快速,对此有任何其他提示?

【问题讨论】:

  • 我看不出自动装箱与这段代码有什么关系。如果您可以对此发表评论,我可以详细说明并希望消除任何混淆。
  • 你不应该在 Java 中使用 new String("hello")。只需写 "hello" - 这已经是一个 String 对象。无需创建另一个 String 对象。

标签: java generics autoboxing


【解决方案1】:

关于类型安全

目前尚不清楚您要做什么,但应该指出的是,您的代码中没有任何类型安全。

Double d = getAnything(0);
// compiles fine, but throws ClassCastException at run time

这首先违背了使用泛型的目的。

您在撰写此声明时引入了这种不安全性:

return (T)o; // warning: Type safety: Unchecked cast from Object to T

相关问题

另见

  • 有效的 Java 第 2 版,第 24 条:消除未经检查的警告

关于类型安全的异构容器

也许您想要 Josh Bloch 所说的 Typesafe Heterogeneous Container 之类的东西。这是 Neal Gafter 博客的引述:

这是一个简单但完整的 API 示例,它在 THC 模式,来自 Josh 2006 年的 JavaOne 演讲:

public class Favorites {

    private Map<Class<?>, Object> favorites =
        new HashMap<Class<?>, Object>();

    public <T> void setFavorite(Class<T> klass, T thing) {
        favorites.put(klass, thing);
    }
    public <T> T getFavorite(Class<T> klass) {
        return klass.cast(favorites.get(klass));
    }

    public static void main(String[] args) {
        Favorites f = new Favorites();
        f.setFavorite(String.class, "Java");
        f.setFavorite(Integer.class, 0xcafebabe);

        String s = f.getFavorite(String.class);
        int i = f.getFavorite(Integer.class);
    }
}

使用这种模式,您可以获得类型安全; int i = f.getFavorite(String.class); 确实编译(这是一件好事!)。

另见


关于自动装箱

自动装箱是从原始int 到引用类型Integer 的隐式转换;自动拆箱是相反的转换。所述问题与自动装箱无关。

另见

相关问题

【讨论】:

    【解决方案2】:

    我认为您将自动装箱与类型推断混淆了。

    类型推断是编译器可以根据调用方法时使用的变量自行判断它应该在泛型方法上使用什么类型。

    例如,如果您有以下方法:

    public <T extends SomeClass> T process(T obj) {
        // call some methods of SomeClass on obj to process it here
        return obj;
    }
    

    然后这样称呼它:

    SomeChildClass a = new SomeChildClass(); // SomeChildClass extends SomeClass
    a = process(a);
    

    推断的类型将是 SomeChildClass;

    可以从参数或返回类型推断类型,如您的示例中所示。但是对于编译器来说,它应该使用什么类型并不总是很明显。如果发生这种情况,您可以使用您描述的方法this.&lt;Double&gt;getAnything(int flag) 强制类型。这通常发生在这样的情况下:

    public <T> List<T> getSomeList() {
        // implementation
    }
    
    public void processList(List<SomeClass> list) {
         // implementation
    }
    

    打电话

    processList(getSomeList()); // compiler error: cannot convert List<Object> to List<SomeClass>
    

    在这种情况下,您可能需要强制类型参数。

    话虽如此,请考虑 polygenelubricants 所说的一切,因为他对您的代码提出了一些非常好的观点并解释了自动装箱是什么(它与原始包装类有关,例如 Integer 用于 int,Double 用于 double )。

    【讨论】:

      猜你喜欢
      • 2010-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-19
      • 2011-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多