Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way of imitating OR in Java Generics

EDIT: I changed a bit the example for getting the idea:

Like

 <Integer or Float>

...without having to create a common interface and make a subclass for Integer and Float to implement it

If not, something like this would maybe have more sense and be useful

 <E extends Number> <E = (Integer|Float)>

If ? is a wildcard why should not we allowed to restrict certain types?

like image 591
Whimusical Avatar asked Jul 24 '12 14:07

Whimusical


People also ask

Can you instantiate a generic?

Generic types are instantiated to form parameterized types by providing actual type arguments that replace the formal type parameters. A class like LinkedList<E> is a generic type, that has a type parameter E .

Is it possible to return a generic type in Java?

(Yes, this is legal code; see Java Generics: Generic type defined as return type only.) The return type will be inferred from the caller. However, note the @SuppressWarnings annotation: that tells you that this code isn't typesafe. You have to verify it yourself, or you could get ClassCastExceptions at runtime.

Does Java have generic methods?

Java Generic methods and generic classes enable programmers to specify, with a single method declaration, a set of related methods, or with a single class declaration, a set of related types, respectively. Generics also provide compile-time type safety that allows programmers to catch invalid types at compile time.


2 Answers

It's not possible and I hardly see any value in it. You use generics to restrict type, e.g. in collections. With or operator you know as much about the type as much you know about the most specific supertype of both of them, Object in this case. So why not just use Object?

Hypothetical:

List<E extends String or Number> list = //...

What is the type of list.get(0)? Is it String or Number? But you cannot have a variable of such type. It cannot be String, it cannot be Number - it can only be... Object.

UPDATE: Since you changed your example in question to:

<Integer or Float>

why won't you just say:

<Number>

? Note that Number has methods that allow you to easily extract floatValue() and intValue(). Do you really need the exact type?


Note that you can use and operator:

<E extends Serializable & Closeable>

And that makes perfect sense - you can use variable of type E where either Serializable or Closeable is needed. In other words E must extend both Serializable and Closeable. See also: Java Generics Wildcarding With Multiple Classes.

like image 60
Tomasz Nurkiewicz Avatar answered Oct 14 '22 15:10

Tomasz Nurkiewicz


In very extreme cases (pre-Java 7 without AutoCloseable), I would have liked to be able to do that, too. E.g.

<E extends Connection or Statement or ResultSet>

That would've allowed me to call E.close(), no matter what the actual type was. In other words, E would contain the "API intersection" of all supplied types. In this case it would contain close(), and all methods from java.sql.Wrapper and java.lang.Object.

But unfortunately, you cannot do that. Instead, use method overloading, e.g.

void close(Connection c);
void close(Statement s);
void close(ResultSet r);

Or plain old instanceof

if (obj instanceof Connection) {
    ((Connection) obj).close();
}
else if (obj instanceof Statement) { //...

Or fix your design, as you probably shouldn't have to intersect APIs of arbitrary types anyway

like image 39
Lukas Eder Avatar answered Oct 14 '22 14:10

Lukas Eder