关于泛型擦除的问题提问

有这么一个方法


private static <T, V> void test(Function<T, V> func, V val) {}

这么写会正常报错

Function<UrlEntity, Integer> a = UrlEntity::getConnectTimeout;
test(a, "1");

而这么写却不会报错

test(UrlEntity::getConnectTimeout, "1");

其中UrlEntity::getConnectTimeout是Integer类型的

我想在用第二种方法的时候也想像第一种写法一样报错,我应该要怎么改?

你可以看看这个:

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 以下回答由chatgpt基于相关博客总结生成:

    问题分析: 这个问题涉及到Java泛型擦除机制以及类型推断的相关知识。方法参数的类型是由编译器进行类型推断的,而在第一种写法中,类型推断会使用传入参数的类型来确定泛型的具体类型,因此不会报错。而在第二种写法中,编译器无法直接确定泛型的具体类型,因此会根据参数类型的上下文进行类型推断,并且类型推断会忽略掉参数的实际类型。

    解决方案: 要想在第二种写法中报错,需要利用一个辅助方法来强制指定泛型的具体类型。 具体步骤如下:

    1. 修改test方法,增加一个额外的泛型类型参数R,用于指定泛型类型。
    private static <T, V, R> void test(Function<T, V> func, R type, V val) {}
    
    1. 在辅助方法中对func进行类型转换,将其强制转换为Function类型。
    @SuppressWarnings("unchecked")
    private static <T, V, R> void test(Function<T, V> func, R type, V val) {
        Function<T, R> funcWithCast = (Function<T, R>) func;
        // 进行你的其他操作
    }
    
    1. 在调用test方法时,传入一个辅助参数来指定泛型的具体类型。
    test(UrlEntity::getConnectTimeout, Integer.class, "1");
    

    使用这种方法,即使在第二种写法中,当指定的辅助参数和返回类型不匹配时,也会在编译阶段报错。

    完整代码如下:

    import java.util.function.Function;
    
    public class Main {
        public static void main(String[] args) {
            test(UrlEntity::getConnectTimeout, Integer.class, "1");
        }
    
        @SuppressWarnings("unchecked")
        private static <T, V, R> void test(Function<T, V> func, R type, V val) {
            Function<T, R> funcWithCast = (Function<T, R>) func;
            // 进行你的其他操作
        }
    }
    
    class UrlEntity {
        public static Integer getConnectTimeout(UrlEntity urlEntity) {
            return 100;
        }
    }
    

    这样做的缺点是需要引入一个额外的参数来指定泛型的具体类型,但能够使程序在编译时期就能发现类型不匹配的错误。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

第二种写法没有报错是因为在调用test方法时直接使用了方法引用UrlEntity::getConnectTimeout,而不是将方法引用赋值给一个变量再传递给test方法, 如果你想在第二种写法中也实现报错功能,可以修改test方法的定义,使其接受一个Supplier而不是一个Function。这样,你可以在test方法内部对传入的方法进行调用并捕获异常,然后抛出适当的异常或输出错误信息。
示例

private static <T> void test(Supplier<T> supplier, T val) {
    try {
        T result = supplier.get();
    } catch (Exception e) {
        // 抛出适当的异常或输出错误信息
    }
}

调用


test(UrlEntity::getConnectTimeout, "1");

如有帮助给个采纳谢谢

test里面代码是怎么写的