简体   繁体   中英

Uniform parameters passing and typesafety with Java generics

Since I often have to deal with randomization, I'd like to make a class which conveniently groups all of those functions that I usually need. Among others, I thought of a generic fromPool() function which, given a variable number of objects, returns randomly one of them. Of course I had to combine varargs and generics, which I just discovered could be a big taboo depending on the cases (and I suspect mine is one of those). Here's the code:

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)];
    }
}

The problem is that I can of course pass to fromPool() objects of different kinds, making the return type extremely variable. So, for example, I can do something like this:

int n = (int) RandomGenerator.fromPool("String", 6);

Which will work until fromPool() doesn't return "String", then causing this exception to be thrown.

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)

Here's what I was wondering:

1) Is this what the "Type safety: Potential heap pollution via varargs parameter pool" warning which appears when combining generics and varargs refers to? Is there something more to it?

2) Isn't there a way to limit the generics effect so that you couldn't pass objects that aren't in any way compatible to each other to the same function call? Basically some kind of automatic, transversal overloading (I feel like I'm asking for the moon)?

3) I had actually previously wrote a much less generic version of fromPool() which only dealt with Number objects.

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

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

Contrary to what I initially believed, it ends this version is unsafe as well because while casting between primitive types doesn't create any problems, casting between the various wrapper classes is not possible, so causing once again ClassCastExceptions. Isn't there a way to tweak this version in order to make at least this one safe?

Thank you very much for your insight :)

You can try something like the one below.

RandomGenerator.<String>fromPool("String", "Something");

By doing so, you will be explicitly specifying the generic object type for that function call. And also you need not to cast your return value since the generic type is explicitly declared.

When you don't specify the generic object type it will be inferred as java.lang.Object .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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