In the generic Java class, add additional general constructor-level constraints?

I have an interface called Bar and a general Foo class parameterized by type Bar :

 class Foo<B extends Bar> { } 

My class has a general purpose constructor that accepts Class and Stream :

 class Foo<B extends Bar> { B[] bs; Foo(Class<B> clazz, Stream<B> stream) { // General ctor bs = someFunctionOf(clazz, stream); } } 

I am trying to add a specialized constructor that requires that its actual method parameter be the Bar and enum class, so I can call my general purpose constructor from a special constructor:

 class Foo<B extends Bar> { B[] bs; Foo(Class<B> clazz, Stream<B> stream) { // General ctor bs = someFunctionOf(clazz, stream); } // FIX THIS ----+ // | // ˅ Foo(Class<Something> clazz) { // Special ctor // Can we make this work so Something is a Bar and an enum // and we can call the other constructor like this? this(clazz, Arrays.stream(clazz.getEnumConstants()); } } 
+7
java generics constructor bounds
source share
3 answers

Generally speaking, you can write generic constructors. We recently had a question about them and how they can be useful . So you can provide a constructor that takes as an argument a class representing a class that extends some specific other class and implements the Bar interface:

 class Foo<B extends Bar> { B[] bs; Foo(Class<B> clazz, Stream<B> stream) { // General ctor bs = someFunctionOf(clazz, stream); } private B[] someFunctionOf(Class<B> clazz, Stream<B> stream) { return null; } <T extends SomeClass & Bar> Foo(Class<T> clazz) { // ... } } 

But this is not quite the way you want, because the bounds of an argument of type T constructor must be explicit types. Typical variables, such as a type parameter of class B , are not served, and without a way to connect T to B special generic constructor cannot invoke a common constructor.

But you can do this using the factory method instead of a special constructor:

 class Foo<B extends Bar> { B[] bs; Foo(Class<B> clazz, Stream<B> stream) { // General ctor bs = someFunctionOf(clazz, stream); } private B[] someFunctionOf(Class<B> clazz, Stream<B> stream) { return null; } static <T extends Enum<T> & Bar> Foo<T> createEnumFoo(Class<T> clazz) { return new Foo<>(clazz, Arrays.stream(clazz.getEnumConstants())); } } 
+6
source share

I do not think you can do this with a constructor. Or create a subclass:

 class EnumFoo<B extends Enum<B>&Bar> extends Foo<B> { public EnumFoo(Class<B> clazz) { super(clazz, Arrays.stream(clazz.getEnumConstants())); } } 

or factory:

 public static <T extends Enum<T>&Bar> Foo<T> of(Class<T> clazz) { return new Foo<>(clazz, Arrays.stream(clazz.getEnumConstants())); } 
+5
source share

This is possible using the and operator: <Something extends Bar & Enum<?>>

-4
source share

All Articles