繁体   English   中英

Java通用高级用法

[英]Java Generic Advanced Usage

问题是,如果通用签名包含多个? ,以下代码将无法编译? 都是相同的类型。

import java.util.Map;
import java.util.HashMap;
import java.util.function.Function;

public class Test {

    private static <T> T findSelfReference(Map<T, T> map) {
        for (Map.Entry<T, T> entry : map.entrySet()) {
            if (entry.getKey() == entry.getValue()) {
                return entry.getKey();
            }
        }
        return null;
    }

    private static <T> T findSelfReference2(Map<T, T> map) {
        for (T key : map.keySet()) {
            if (map.get(key) == key) {
                return key;
            }
        }
        return null;
    }

    // Question: How to write the method signature that can ensure compile-time type safety? Both the signatures fail to compile.

    // private static <T> String fun(Function<Map<T, T>, T> finder) {
    private static String fun(Function<Map<?, ?>, ?> finder) {
        Map<Integer, Integer> map1 = new HashMap<>();
        // some processing to map1
        Integer n = finder.apply(map1);  // usage here, compile-time type checking wanted

        Map<String, String> map2 = new HashMap<>();
        // other processing to map2 depending on n
        return finder.apply(finder, map2);  // another usage
    }

    public static void main(String[] args) {
        // Please don't change into helper class...
        System.out.println(fun(Test::findSelfReference));
        System.out.println(fun(Test::findSelfReference2));
    }
}

fun ,在每次对finder.apply()的调用中,类型T是固定的。 但是在不同的呼叫中,它们使用不同的类型。 我尝试了通配符捕获(ref: here ),但是没有运气。

我不想将结果强制转换为必须在运行时进行检查的对象。 所有类型检查都应在编译时完成。

是否可以不建立O(n)辅助类,其中n是内联函数的数目?

问题是您希望finderapply方法是通用的。

解决方案是使用通用方法定义自己的功能接口。

@FunctionalInterface
interface Finder {
    <T> T apply(Map<T, T> map);
}

private static String fun(Finder finder) {
    // same body
}

如果这算作“帮助类”,那我不知道该怎么说。 您正在尝试将方形钉敲入圆孔。 Function#apply不是通用方法,因此您无法使用Function来执行此操作。

您到底想用方法的fun实现什么?

您可以通过通配符或类型参数TFunction传递Function ,然后将其应用于两种不同的具体类型( IntegerString )。

这是行不通的:

Map<Integer, Integer> map1 = new HashMap<>();
// ...
Integer n = finder.apply(map1);

因为在这里您希望finder取一个Integer类型,但是您在fun的声明中已指定该类型是未知的(如果使用?声明)或某个无界的T类型(如果使用type参数声明的话) T )。 但是,如果要将其应用于Integer ,则需要Function<Map<Integer, Integer>> ,而不是Function<Map<?, ?>, ?>Function<Map<T, T>, T>对于一些无界类型T

您可以这样写-但fun方法本身或多或少没有用。

private static <T> T fun(Map<T, T> map, Function<Map<T, T>, T> finder) {
    return finder.apply(map);
}

public static void main(String[] args) {
    Map<Integer, Integer> map1 = new HashMap<>();
    map1.put(1, 2);
    map1.put(3, 4);
    map1.put(5, 7);
    map1.put(2, 2);
    map1.put(8, 8);
    Integer n = fun(map1, Test::findSelfReference);

    String a = String.valueOf(n + 1);
    Map<String, String> map2 = new HashMap<>();
    map2.put("1", "2");
    map2.put("3", "4");
    map2.put("5", "7");
    map2.put("3", a);
    String s = fun(map2, Test::findSelfReference2);

    System.out.println(n);
    System.out.println(s);
}

好吧,你可以做这样的事情:

private static <T> T fun(Function<Map<T, T>, T> finder, Map<T, T> map) {
    return finder.apply(map);
}

private static Map<String, String> getStringMap(Integer n) {
    String a = String.valueOf(n + 1);
    Map<String, String> map2 = new HashMap<>();
    map2.put("1", "2");
    map2.put("3", "4");
    map2.put("5", "7");
    map2.put("3", a);
    return map2;
}

private static Map<Integer, Integer> getIntMap() {
    Map<Integer, Integer> map1 = new HashMap<>();
    map1.put(1, 2);
    map1.put(3, 4);
    map1.put(5, 7);
    map1.put(2, 2);
    map1.put(8, 8);
    return map1;
}

public static void main(String[] args) {
    fun(Test::findSelfReference, getIntMap());
    fun(Test::findSelfReference, getStringMap(1));
}

当您始终可以执行此操作时,我看不到fun方法的用途:

Function<Map<Integer, Integer>, Integer> m = Test::findSelfReference;
m.apply(getIntMap());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM