Java泛型的统一参数传递和类型安全

Java泛型的统一参数传递和类型安全,java,generics,variadic-functions,type-safety,Java,Generics,Variadic Functions,Type Safety,因为我经常要处理随机化,所以我想创建一个类,方便地对我通常需要的所有函数进行分组。除此之外,我还想到了一个通用的fromPool函数,该函数给定了数量可变的对象,随机返回其中一个。当然,我必须结合varargs和泛型,我刚刚发现这可能是一个很大的禁忌,这取决于案例,我怀疑我的就是其中之一。 代码如下: abstract public class RandomGenerator { public static int fromRange(int min, int max) {

因为我经常要处理随机化,所以我想创建一个类,方便地对我通常需要的所有函数进行分组。除此之外,我还想到了一个通用的fromPool函数,该函数给定了数量可变的对象,随机返回其中一个。当然,我必须结合varargs和泛型,我刚刚发现这可能是一个很大的禁忌,这取决于案例,我怀疑我的就是其中之一。 代码如下:

abstract public class RandomGenerator {

    public static int fromRange(int min, int max) {

        return (int) (Math.random() * (max + 1 - min)) + min;
    }

    public static <T> T fromPool(T ... pool) {

        return pool[fromRange(0, pool.length - 1)];
    }
}

它将一直工作,直到fromPool不返回字符串,然后引发此异常

线程主java.lang.ClassCastException中的异常:类 无法将java.lang.String转换为类java.lang.Integer java.lang.String和java.lang.Integer位于的模块java.base中 Test.mainTest.java:109处的加载程序“引导”

我想知道的是:

1这就是类型安全性:通过结合泛型和varargs时出现的varargs参数池警告的潜在堆污染吗?还有别的吗

2是否有一种方法可以限制泛型的效果,这样就不能将互不兼容的对象传递给同一个函数调用?基本上是某种自动的横向过载,我觉得我是在要求月亮

实际上,我以前写过一个不太通用的fromPool版本,它只处理数字对象

public static <N extends Number> N fromPool(N ... pool) {

    return pool[fromRange(0, pool.length - 1)];
}
与我最初认为的相反,这个版本也是不安全的,因为虽然在基本类型之间进行强制转换不会产生任何问题,但在各种包装类之间进行强制转换是不可能的,因此再次导致ClassCastException。难道没有办法调整这个版本以使它至少安全吗


非常感谢您的见解:

您可以尝试下面的方法

RandomGenerator.<String>fromPool("String", "Something");
通过这样做,您将显式指定该函数调用的通用对象类型。而且,由于泛型类型是显式声明的,因此不需要强制转换返回值


如果不指定泛型对象类型,它将被推断为java.lang.object。

我觉得问题在于调用方,而不是函数。为什么你要将不同类型的变量传递到同一个变量函数中,然后只将其转换到其中一种类型?@NathanMerrill那么你认为这不是什么大问题,我应该忽略这一点吗?我觉得这种事情无论如何都应该引起关注。因为依赖程序员的纪律是危险的。我这样想是不是错了?你应该确保你的函数不会抛出错误。但是如果程序员决定将它强制转换到你的函数之外,那就完全超出了你的控制,也超出了你的考虑。好吧。让我觉得我应该担心的是,通常编译器会阻止这种无意义的强制转换。例如,如果字符串被直接强制转换为int,我就无法编译,而这个函数可以实现这样的错误。我不知道,谢谢!但是为什么编译器不强烈推荐类型推断呢?例如,当实例化一个使用泛型(例如任何集合)的类时,会弹出一条警告,建议推断类型。为什么不在这里发生?还有,那类安全警告呢。我应该忽略它吗?在java中,一切都是对象。所以,无论我们在哪里使用泛型类型,如果不显式指定类型,它都将被推断为对象。这同样适用于您在问题中提供的方法示例。关于警告,建议始终明确指定对象类型,而不是忽略。如果你忽略了这些,那么你的代码中就会有太多的对象强制转换,这反过来会使你的代码更容易出错。我不是指类型推断警告,而是指类型安全:通过varargs参数的潜在堆污染,每次varargs和泛型一起使用时都会出现。只要在使用该函数时推断出类型,我是否可以在不害怕任何事情的情况下抑制该警告@SafeVarargs?忽视这个错误是一种好的做法吗?换句话说,我的泛型fromPool函数从根本上是有缺陷的还是可以接受的?是的。只要在使用该函数时推断出类型,它就会起作用。可以通过注释来抑制警告。
RandomGenerator.<String>fromPool("String", "Something");