I have a concrete type (“B”) which is a subtype of several other types (“A1”, “A2” in the example below), and I want to create a method that possibly returns the supertype, or B. So essentially I want to require that B is a subtype of my generic parameter. A code example might make it clearer:
<code>class Scratch {
interface A1 {
default void print1() { System.out.println("A1"); }
}
interface A2 {
default void print2() { System.out.println("A2"); }
}
interface A3 {
default void print3() { System.out.println("A3"); }
}
static class A1Impl implements A1 {}
static class A2Impl implements A2 {}
static class A3Impl implements A3 {}
static class B implements A1, A2 {}
// Is there any way to make this fail at compile-time if B is not a subtype of T?
static <T> Optional<T> get(Supplier<T> provider, Class<T> clazz) {
if (someCondition()) {
return Optional.of(provider.get());
} else {
// I want to avoid an unchecked cast here to get compile-time safety
return Optional.of((T) new B());
}
}
public static void main(String[] args) {
// Should succeed because B is a subtype of A1 and A2
get(A1Impl::new, A1.class).ifPresent(A1::print1);
get(A2Impl::new, A2.class).ifPresent(A2::print2);
// Will fail at run-time because B is not a subtype of A3
// Is there any way to make this fail at compile-time?
get(A3Impl::new, A3.class).ifPresent(A3::print3);
}
}
</code>
<code>class Scratch {
interface A1 {
default void print1() { System.out.println("A1"); }
}
interface A2 {
default void print2() { System.out.println("A2"); }
}
interface A3 {
default void print3() { System.out.println("A3"); }
}
static class A1Impl implements A1 {}
static class A2Impl implements A2 {}
static class A3Impl implements A3 {}
static class B implements A1, A2 {}
// Is there any way to make this fail at compile-time if B is not a subtype of T?
static <T> Optional<T> get(Supplier<T> provider, Class<T> clazz) {
if (someCondition()) {
return Optional.of(provider.get());
} else {
// I want to avoid an unchecked cast here to get compile-time safety
return Optional.of((T) new B());
}
}
public static void main(String[] args) {
// Should succeed because B is a subtype of A1 and A2
get(A1Impl::new, A1.class).ifPresent(A1::print1);
get(A2Impl::new, A2.class).ifPresent(A2::print2);
// Will fail at run-time because B is not a subtype of A3
// Is there any way to make this fail at compile-time?
get(A3Impl::new, A3.class).ifPresent(A3::print3);
}
}
</code>
class Scratch {
interface A1 {
default void print1() { System.out.println("A1"); }
}
interface A2 {
default void print2() { System.out.println("A2"); }
}
interface A3 {
default void print3() { System.out.println("A3"); }
}
static class A1Impl implements A1 {}
static class A2Impl implements A2 {}
static class A3Impl implements A3 {}
static class B implements A1, A2 {}
// Is there any way to make this fail at compile-time if B is not a subtype of T?
static <T> Optional<T> get(Supplier<T> provider, Class<T> clazz) {
if (someCondition()) {
return Optional.of(provider.get());
} else {
// I want to avoid an unchecked cast here to get compile-time safety
return Optional.of((T) new B());
}
}
public static void main(String[] args) {
// Should succeed because B is a subtype of A1 and A2
get(A1Impl::new, A1.class).ifPresent(A1::print1);
get(A2Impl::new, A2.class).ifPresent(A2::print2);
// Will fail at run-time because B is not a subtype of A3
// Is there any way to make this fail at compile-time?
get(A3Impl::new, A3.class).ifPresent(A3::print3);
}
}
Ideally, one would like something like
<code>static <T super B> Optional<T> get(Supplier<T> provider, Class<T> clazz)
</code>
<code>static <T super B> Optional<T> get(Supplier<T> provider, Class<T> clazz)
</code>
static <T super B> Optional<T> get(Supplier<T> provider, Class<T> clazz)
but I am aware that is not possible in Java. Is there any way to achieve compile-time safety here?