正如 Afonso 所建议的,另一种可能性是创建一个函数并写下所有必需的可能性。以下是一些变化:
// Examples with static functions:
Integer i = addNumbers (1, 2); // OK
Double d = addNumbers (3.0, 4.0); // OK
String s = addObjects ("a", "b"); // OK
//
// Example with a raw type for a class with both method
// (or member function) and static functions:
GenericClass gc = new GenericClass(); // Raw type
//
// Note the error if we don't add a cast:
// i = gc.add(1, 2); // Error: Cannot convert from Number to Integer
//
// Now OK with a cast but with a Type safety warning:
i = (Integer) gc.add (1, 2); // Type safety warning.
i = GenericClass.add2 (1, 2); // OK
i = GenericClass.add3 (1, 2); // OK
//
// Example with an instanciated type for the same class:
GenericClass<Integer> gc1 = new GenericClass<Integer>();
//
// Note that we don't need a cast anymore:
i = gc1.add(1, 2); // Now OK even without casting.
//
i = GenericClass2.add2 (1, 2); // OK
s = GenericClass2.add2 ("a", "b"); // OK
i = GenericClass2.<Integer>add2 (1, 2); // OK.
d = GenericClass2.<Double>add2 (1.0, 2.0); // OK
s = GenericClass2.<String>add2 ("a", "b"); // OK
//
public static<T extends Number> T addNumbers(T x, T y) {
if (x instanceof Integer && y instanceof Integer){
return (T) (Integer) ((Integer)x + (Integer)y);
} else if (x instanceof Double && y instanceof Double){
return (T) (Double) ((Double)x + (Double)y);
} else
return (T)null;
}
//
public static<T> T addObjects(T x, T y) {
if (x instanceof Integer && y instanceof Integer) {
//
// We must add an (Integer) cast because the type of the operation
// "((Integer)x + (Integer)y))" is "int" and not "Integer" and we
// cannot directly convert from "int" to "T". Same thing for Double
// but not for the type String:
//
return (T) (Integer) ((Integer)x + (Integer)y);
} else if (x instanceof Double && y instanceof Double) {
return (T) (Double) ((Double)x + (Double)y);
} else if (x instanceof String && y instanceof String) {
return (T) ((String)x + (String)y);
} else
return (T)null;
}
//
static class GenericClass<T extends Number> {
public T add(T x, T y) {
if (x instanceof Integer && y instanceof Integer) {
return (T) (Integer) ((Integer)x + (Integer)y);
} else if (x instanceof Double && y instanceof Double) {
return (T) (Double) ((Double)x + (Double)y);
} else
return (T)null;
}
//
// The type <T> here is NOT the same as the one for the class.
// We should rename it in order to make this clearer. See add3()
// for an example of this.
public static<T> T add2(T x, T y) {
if (x instanceof Integer && y instanceof Integer) {
return (T) (Integer) ((Integer)x + (Integer)y);
} else if (x instanceof Double && y instanceof Double) {
return (T) (Double) ((Double)x + (Double)y);
} else if (x instanceof String && y instanceof String) {
return (T) ((String)x + (String)y);
} else
return (T)null;
}
//
// The type here is not the same as the one for the class
// so we have renamed it from <T> to <N> to make it clearer.
public static<N extends Number> N add3(N x, N y) {
if (x instanceof Integer && y instanceof Integer) {
return (N) (Integer) ((Integer)x + (Integer)y);
} else if (x instanceof Double && y instanceof Double) {
return (N) (Double) ((Double)x + (Double)y);
} else
return (N)null;
}
}