Java 静态成员中的泛型参数声明

Java 静态成员中的泛型参数声明,java,generics,Java,Generics,不允许定义此类静态成员的原因: private static final <T extends Object> Map<Class<T>, BiFunction<T, T, Boolean>> SPECIFIC_HANDLERS = new HashMap<>(); 构造(根据Mena)甚至不编译: private static <T extends Object> Map<Class<T>, BiFun

不允许定义此类静态成员的原因:

private static final <T extends Object> Map<Class<T>, BiFunction<T, T, Boolean>> SPECIFIC_HANDLERS = new HashMap<>();
构造(根据Mena)甚至不编译:

private static <T extends Object> Map<Class<T>, BiFunction<T, T, Boolean>> getSpecificHandlers() 
{
    Map<Class<T>, BiFunction<T, T, Boolean>> result = new HashMap<>();
    result.put( Object[].class,  (l, r) -> Arrays.equals( (Object[])  l, (Object[])  r ));
    result.put( boolean[].class, (l, r) -> Arrays.equals( (boolean[]) l, (boolean[]) r ));
    return result;
}
private静态映射getSpecificHandlers()
{
映射结果=新的HashMap();
put(Object[].class,(l,r)->array.equals((Object[])l,(Object[])r));
put(boolean[].class,(l,r)->array.equals((boolean[])l,(boolean[])r));
返回结果;
}
如果我在方法之外填充生成的映射:

 @SuppressWarnings( { "unchecked", "rawtypes" })
private static final Map<Class<?>, BiFunction<?, ?, Boolean>> ARRAY_EQUALS_HANDLER = (Map) getSpecificHandlers();

static
{
    ARRAY_EQUALS_HANDLER.put( Object[].class,  (l, r) -> Arrays.equals( (Object[])  l, (Object[])  r ));
    ...
}
@SuppressWarnings({“unchecked”,“rawtypes”})

private static final Map对于常量声明,您使用的是泛型方法惯用法(返回类型之前的类型参数声明)

那个成语不会被编译

正如其他地方提到的,您不能在静态上下文中使用类泛型类型

作为一种解决方法,您可以声明一个静态方法,而不是常量,具体如下:

private static final <T extends WhateverBound> Map<Class<T>, 
    BiFunction<T, T, Boolean>> 
    getSpecificHandlers(T t) {

    // return new HashMap<Class<T>, BiFunction<T, T, Boolean>>();
    // much easier on the eye - thanks Andy Turner
    return new HashMap<>();
}
然后,您可以通过以下方式调用您的方法:

Map<Class<Foo>, BiFunction<Foo, Foo, Boolean>> map = 
getSpecificHandlers(new Foo());

我有一个解决方案,它有点难看,但按要求工作

首先,请注意,
Map.get()
方法将原始
对象
类型作为参数,因此编译器不可能根据参数类型猜测此方法的返回类型。返回类型不是来自字段本身的声明,而是使用固定类型参数声明的(在您的情况下,它应该是
对象
)-您可以为
.get()的任何调用获得固定的返回类型。实际上,同样的事情不仅适用于
get()
方法,而且适用于所有您希望充当类型参数化方法的方法

其次,所需的结构应该对键和值对添加一些限制(您希望值类型取决于键类型)。这通常通过类型参数完成。它不适用于字段声明,但适用于类型或方法声明

因此,在这两个前提下,我以解决方案结束:引入扩展
Map
的类型,使用附加的类型关联和附加的泛型
get()
方法(当然,您可以添加更多泛型方法)


publicstaticclasshandlermap扩展了HashMap我认为仅仅使用成员声明是不可能的。您可以做的是隐藏地图本身,并为访问地图提供更严格的方法

例如,像这样:

class FunctionMapper {

    private final Map<Class<?>, BiFunction<?, ?, Boolean>> MAP = new HashMap<>();

    public <T> void map(Class<T> c, BiFunction<T, T, Boolean> f) {
        MAP.put(c, f);
    }

    public <T> BiFunction<T, T, Boolean> get(Class<T> c) {
        return (BiFunction<T, T, Boolean>) MAP.get(c);
    }

    public <T> Boolean apply(T o1, T o2) {
        return get((Class<T>) o1.getClass()).apply(o1, o2);
    }
}
    FunctionMapper mapper = new FunctionMapper(); // make this static final
    mapper.map(String.class, (s1, s2) -> s1.compareTo(s2) == 0);
    System.out.println(mapper.apply("foo", "bar"));

如果是静态成员,则只能有一个实例。在这种情况下,泛型是没有意义的。。。或者,可以将其设置为单例?如果它是静态的,而不是最终的,那么该引用可能会有许多赋值。@ReutSharabani实际上,它是
静态的
最终的
。@tobias_k没有谈论这个特殊情况:)已编辑。@yturner-hah会的!谢谢你的关注,谢谢你的想法。但就我而言,它不起作用。这个construct@Heri不客气。从你的评论中不清楚什么不适合你…抱歉,我想在这里解释原因,但点击回车键太快了。见我上面更新的问题
private static final <T extends WhateverBound> Map<Class<T>, 
    BiFunction<T, T, Boolean>> 
    getSpecificHandlers(T t) {

    // return new HashMap<Class<T>, BiFunction<T, T, Boolean>>();
    // much easier on the eye - thanks Andy Turner
    return new HashMap<>();
}
static class WhateverBound{}
static class Foo extends WhateverBound {}
Map<Class<Foo>, BiFunction<Foo, Foo, Boolean>> map = 
getSpecificHandlers(new Foo());
private static final Map<Class<? extends WhateverBound>, 
     BiFunction<? extends WhateverBound, ? extends WhateverBound, Boolean>> 
       SPECIFIC_HANDLERS = new HashMap<>();

static {
    SPECIFIC_HANDLERS.put(Foo.class, (f, ff) -> true);
}
public static class HandlerMap<T> extends HashMap<Class<? extends T>, BiFunction<T, T, Boolean>> {
    @SuppressWarnings("unchecked")
    <U extends T> BiFunction<U, U, Boolean> getStrict(Class<? extends U> key) {
        return (BiFunction<U, U, Boolean>) get(key);
    }
}

private static HandlerMap<Object> ARRAY_EQUALS_HANDLER = new HandlerMap<>();

static {
    ARRAY_EQUALS_HANDLER.put(Object[].class, (l, r) -> Arrays.equals((Object[]) l, (Object[]) r));
    ARRAY_EQUALS_HANDLER.put(boolean[].class, (l, r) -> Arrays.equals((boolean[]) l, (boolean[]) r));

    //WARNING - type safety breaks here
    ARRAY_EQUALS_HANDLER.put(int[].class, (l, r) -> Arrays.equals((boolean[]) l, (boolean[]) r));

}
public static void main(String[] args) throws Exception {
    BiFunction<int[], int[], Boolean> biFunction = ARRAY_EQUALS_HANDLER.getStrict(int[].class);
}
class FunctionMapper {

    private final Map<Class<?>, BiFunction<?, ?, Boolean>> MAP = new HashMap<>();

    public <T> void map(Class<T> c, BiFunction<T, T, Boolean> f) {
        MAP.put(c, f);
    }

    public <T> BiFunction<T, T, Boolean> get(Class<T> c) {
        return (BiFunction<T, T, Boolean>) MAP.get(c);
    }

    public <T> Boolean apply(T o1, T o2) {
        return get((Class<T>) o1.getClass()).apply(o1, o2);
    }
}
    FunctionMapper mapper = new FunctionMapper(); // make this static final
    mapper.map(String.class, (s1, s2) -> s1.compareTo(s2) == 0);
    System.out.println(mapper.apply("foo", "bar"));