【问题标题】:Not implementing generic method in generics class没有在泛型类中实现泛型方法
【发布时间】:2016-10-29 21:35:44
【问题描述】:

想象一下这样的代码:

public class Value<T> {
    private T value;

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

    public int size() {
        return sizeOf(value);
    }

    private int sizeOf(int value) {
        return Integer.BYTES;
    }

    private int sizeOf(String value) {
        return value.length() * Character.BYTES;
    }
}

在某处(例如main

Value<String> value = new Value<String>("hello");

问题是代码不会编译,因为我还没有实现sizeOf(T value)但是我不明白为什么编译器会抱怨---它看到我只用它和@987654330 @。如果我实现通用 sizeOf(T value) ,它将优先(如此处所述 Java generics (template) specialization possible (overriding template types with specific types)

请注意,那里提出的解决方案(有一个StringValue 子类)并不真正适用于我的情况,因为我已经有一些我正在使用的子类,所以我需要创建很多额外的类(时间类型)

但我更喜欢更直接的东西,比如这个

【问题讨论】:

  • "但我不明白编译器为什么会抱怨 --- 它看到我只将它与 &lt;T=String&gt; 一起使用" - 这不是泛型在 Java 中的工作方式。它们与 C++ 的模板变量完全不同。您需要一个满足T 给出的错误的方法sizeOf

标签: java generics inheritance


【解决方案1】:

您必须声明sizeOf(T value),因为T 可以是任何类型,因此为了维护类型控制,编译器需要sizeOf 方法的“通用”版本,该方法将隐藏任何可能的类型。

想想如果你使用new Value&lt;List&lt;Object&gt;&gt;(new ArrayList&lt;Object&gt;).size() 之类的东西会发生什么 - 如果你没有专门用于返回集合大小的方法会发生什么?

问题是,在运行时,泛型类型被删除,所以 JVM 不知道应该使用哪些重载方法。在此处查看有关类型擦除的更多信息。 https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

【讨论】:

    【解决方案2】:

    不必为size() 提供实现。你的代码是双重分派模式的一半,但不可能一直走下去,因为你没有办法要求像 String 这样的类型来实现size()

    一种方法是在构造时要求尺寸代码:

    public class Value<T> {
        private T value;
        private Function<T, Integer> size;
    
        public Value(T value, Function<T, Integer> size) {
            this.value = value;
            this.size;
        }
    
        public int size() {
            return size.apply(value);
        }
    }
    

    以创建Value&lt;String&gt; 为例:

     Value<String> val = new Value("foo", s -> s.length() * Character.BYTES)
    

    或者如果这不起作用,请使用instanceof 获取支持的类型:

    public int size() {
        if (value instanceof Integer)
            return Integer.BYTES;
        if (value instanceof String)
            return ((String)value).length() * Character.BYTES;
        // other supported types
        throw new IllegalStateException();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-10
      • 1970-01-01
      • 2012-12-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多