Is there any way of imitating OR in Java Generics
Asked Answered
R

4

21

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?

Rhymester answered 24/7, 2012 at 14:42 Comment(4)
Why would you want to do that?Executant
They seem like chalk and cheese. The requirement makes no sense to me at all. Are Strings mathematical entities like Numbers, closed over certain operations? I thought not.Temper
Precisely because String is final, an or solution would be needed even more, because we could not solve it with the alternative I proposeRhymester
I think it sounds like you need a real object instead of collection. There's some encapsulation missing here.Temper
G
13

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

Gallager answered 24/7, 2012 at 14:48 Comment(3)
In Java 7 all these classes implement AutoCloseable so <E extends AutoCloseable> is now enough.Wollis
@TomaszNurkiewicz: I know. It's just an illustration. @GriffeyDog: See Tomasz' answer. JDBC types extend AutoCloseable, not Closeable (which also extends AutoCloseable)Gallager
Another similar case swhere it would be useful is Number interface, DOuble, Integer ... have valueOf but Number, the super, does not. Also: when you need T = concrete subtypes but not the super-OR is handyRhymester
W
18

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.

Wollis answered 24/7, 2012 at 14:44 Comment(5)
Ok for list is stupid, but for other uses it could be not like this. Even that you could have a String a = list.get(0) or either a Integer a= list.get(0), ugly but not impossible or impracticle. It could throw a CastExeption if errorRhymester
@user1352530: avoiding ClassCastException and compile time type checking was one of the reasons to include generics in the first place.Wollis
I updated the question with a new approah which makes the same for meRhymester
@User1352530: I feel OR is always confusing and error prone. May be time to re-architect requirement? Specially in Java with casting, I try to avoid OR as much as possible. As Tomasz said in answer AND is supported.Koopman
I hardly see any value in it I want to overload a method, and have version of flatMap(Function1<T, Try<NewT>> mapper) and flatMap(Function1<T, MyCustomCallableThatIsSimilarToTry<NewT>> mapper), but I cannot do it as I get error that their both erasure is the same. When I was searching for OR in generics, I hoped I could use it to ducktape fix this issueHavana
G
13

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

Gallager answered 24/7, 2012 at 14:48 Comment(3)
In Java 7 all these classes implement AutoCloseable so <E extends AutoCloseable> is now enough.Wollis
@TomaszNurkiewicz: I know. It's just an illustration. @GriffeyDog: See Tomasz' answer. JDBC types extend AutoCloseable, not Closeable (which also extends AutoCloseable)Gallager
Another similar case swhere it would be useful is Number interface, DOuble, Integer ... have valueOf but Number, the super, does not. Also: when you need T = concrete subtypes but not the super-OR is handyRhymester
W
0

I don't see a real use for it... But anyways, I believe the closest you'd get to it is extending common interfaces for the possible implementations.

Whitby answered 24/7, 2012 at 14:46 Comment(0)
H
0

Here is the scenario that I have at hand: GraphQL Inputs don't allow the use of interfaces to define common fields, so you might end up having to duplicate (or triplicate, or...) your code to handle inputs that have the same common fields without having to use methods with lots of parameters to achieve the same result. Similarly to what Lukas suggested, having an API intersection of methods that appear in all of the OR-ed classes would greatly help with the problem, but unfortunately, that's not something available besides in Exceptions.

Hypostasize answered 17/5, 2024 at 17:44 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.