Java 泛型的统一参数传递和类型安全
Uniform parameters passing and typesafety with Java generics
因为我经常需要处理随机化,所以我想制作一个 class 来方便地将我通常需要的所有这些功能分组。其中,我想到了一个通用的 fromPool()
函数,给定可变数量的对象,return 随机选择其中一个。当然,我必须结合使用可变参数和泛型,我刚刚发现这可能是一个很大的禁忌,具体取决于情况(我怀疑我的情况就是其中之一)。
这是代码:
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()
不同种类的对象,使 return 类型极其可变。因此,例如,我可以这样做:
int n = (int) RandomGenerator.fromPool("String", 6);
这将一直有效,直到 fromPool()
不 return "String",然后导致抛出此异常。
Exception in thread "main" java.lang.ClassCastException: class
java.lang.String cannot be cast to class java.lang.Integer
(java.lang.String and java.lang.Integer are in module java.base of
loader 'bootstrap') at Test.main(Test.java:109)
这是我想知道的:
1) 泛型和可变参数组合时出现的"Type safety: Potential heap pollution via varargs parameter pool"警告是指这个吗?还有更多吗?
2) 有没有一种方法可以限制泛型效应,这样您就无法将彼此不兼容的对象传递给同一个函数调用?基本上是某种自动的、横向的超载(我觉得我在要求月亮)?
3) 实际上我之前写过一个不太通用的 fromPool()
版本,它只处理 Number 对象。
public static <N extends Number> N fromPool(N ... pool) {
return pool[fromRange(0, pool.length - 1)];
}
与我最初的看法相反,它结束了这个版本也是不安全的,因为虽然在原始类型之间进行转换不会产生任何问题,但在各种包装器 classes 之间进行转换是不可能的,所以导致再次出现 ClassCastExceptions。有没有办法调整这个版本以至少让这个版本安全?
非常感谢您的见解:)
您可以试试下面的方法。
RandomGenerator.<String>fromPool("String", "Something");
通过这样做,您将明确指定该函数调用的通用对象类型。而且你不需要转换你的 return 值,因为泛型类型是显式声明的。
当您不指定通用对象类型时,它将被推断为 java.lang.Object
。
因为我经常需要处理随机化,所以我想制作一个 class 来方便地将我通常需要的所有这些功能分组。其中,我想到了一个通用的 fromPool()
函数,给定可变数量的对象,return 随机选择其中一个。当然,我必须结合使用可变参数和泛型,我刚刚发现这可能是一个很大的禁忌,具体取决于情况(我怀疑我的情况就是其中之一)。
这是代码:
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()
不同种类的对象,使 return 类型极其可变。因此,例如,我可以这样做:
int n = (int) RandomGenerator.fromPool("String", 6);
这将一直有效,直到 fromPool()
不 return "String",然后导致抛出此异常。
Exception in thread "main" java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer (java.lang.String and java.lang.Integer are in module java.base of loader 'bootstrap') at Test.main(Test.java:109)
这是我想知道的:
1) 泛型和可变参数组合时出现的"Type safety: Potential heap pollution via varargs parameter pool"警告是指这个吗?还有更多吗?
2) 有没有一种方法可以限制泛型效应,这样您就无法将彼此不兼容的对象传递给同一个函数调用?基本上是某种自动的、横向的超载(我觉得我在要求月亮)?
3) 实际上我之前写过一个不太通用的 fromPool()
版本,它只处理 Number 对象。
public static <N extends Number> N fromPool(N ... pool) {
return pool[fromRange(0, pool.length - 1)];
}
与我最初的看法相反,它结束了这个版本也是不安全的,因为虽然在原始类型之间进行转换不会产生任何问题,但在各种包装器 classes 之间进行转换是不可能的,所以导致再次出现 ClassCastExceptions。有没有办法调整这个版本以至少让这个版本安全?
非常感谢您的见解:)
您可以试试下面的方法。
RandomGenerator.<String>fromPool("String", "Something");
通过这样做,您将明确指定该函数调用的通用对象类型。而且你不需要转换你的 return 值,因为泛型类型是显式声明的。
当您不指定通用对象类型时,它将被推断为 java.lang.Object
。