Optional arguments to constructors

3,059 views
Skip to first unread message

Martin Grajcar

unread,
Oct 12, 2009, 8:48:33 AM10/12/09
to google...@googlegroups.com
Hi,
is there no way to make contructor arguments optional?
I know there're alternatives, but IMHO none of them is as good as this:

- optional setter injection disadvantages:
the field can't be final
the setter may have no other use
marking the setter as private triggers unused warning

- optional field injection disadvantages:
the field can't be final
the field gets marked as final by my IDE (which I don't want to switch off)

Maybe it can be done in other way, I don't know. The example below illustrates what I mean.


class GuiceOptionalArgumentDemo {
/**
* I'd love if Guice would understand something like this.
* If an argument annotated with Optional si not configured, null gets injected.
*/
@Retention(RUNTIME) public @interface Optional {}

static class SomeClass {
@Inject
SomeClass(@Optional Integer count) {
this.count = count==null ? 42 : count.intValue();
}
public int getCount() {
return count;
}
private final int count;
}

public static void main(String[] args) throws Exception {
Guice.createInjector().getInstance(SomeClass.class);
}
}


Regard, Maaartin.

Gary Pampara

unread,
Oct 12, 2009, 11:13:27 AM10/12/09
to google...@googlegroups.com
Guice refuses to inject null by default, which is a very good thing.

Java doesn't support constructor arguments with defaults, so you would
have to create bindings yourself with the @Optional annotation. Also,
you would also need to add the @Nullable to allow Guice to inject a
null value.

I'm not sure about how this will help though, it seems like the amount
of work associated with this pattern would make it rather undesirable.

Regards,
Gary

limpb...@gmail.com

unread,
Oct 12, 2009, 12:54:50 PM10/12/09
to google-guice
There's a workaround in the FAQ:
http://code.google.com/p/google-guice/wiki/FrequentlyAskedQuestions

How can I inject optional parameters into a constructor?

Neither constructors nor @Provides methods support optional
injection. To work-around this, you can create an inner class that
holds the optional value:

class Car {
private final Engine engine;
private final AirConditioner airConditioner;

@Inject
public Car(Engine engine, AirConditionerHolder
airConditionerHolder) {
this.engine = engine;
this.airConditioner = airConditionerHolder.value;
}

static class AirConditionerHolder {
@Inject(optional=true) AirConditioner value = new
NoOpAirconditioner();
}
}

Martin Grajcar

unread,
Oct 12, 2009, 3:15:22 PM10/12/09
to google...@googlegroups.com
Hi!

Gary Pampara wrote:
> Guice refuses to inject null by default, which is a very good thing.

I know and I agree. Sure, the @Optional annotation would imply @Nullable.
It'd be acceptable for me to be forced to use both annotations,
but if Guice could understand @Optional, it could automatically assume @Nullable.

> Java doesn't support constructor arguments with defaults, so you would
> have to create bindings yourself with the @Optional annotation. Also,
> you would also need to add the @Nullable to allow Guice to inject a
> null value.
>
> I'm not sure about how this will help though, it seems like the amount
> of work associated with this pattern would make it rather undesirable.

I'm not sure if I understand you.
I don't need default arguments values support in Java, actually not even in Guice, as the class could often provide it's own defaults for itself (just like in my example).
The support in Java could be nice, but it's not really necessary, as I can do it with some more lines using overloaded constructors.
But there can be only one constructor annotated with @Inject, so I see no easy way for doing things like this.

The only thing needed here is a way to make Guice happy with an unbound dependance (just like @Nullable makes it happy with dependance bound to null).
To me it looks like there're plenty uses for that, just look how much classes in JDK have (a sort of) optional arguments.

Regards, Maaartin.

Martin Grajcar

unread,
Oct 13, 2009, 4:10:54 PM10/13/09
to google...@googlegroups.com
Hi,

this works, but it needs quite a lot of boilerplate code including a holder class
which must be public in case I want to configure the Car in different package.
If wonder if making Guice recognize an @Optional annotation would be worth the effort.
I think it must be quite simple, it can make no harm, the only question is
if I'm the only one who'd use it. Do you think it's bad idea?

Regards, Maaartin.

limpb...@gmail.com

unread,
Oct 13, 2009, 9:21:39 PM10/13/09
to google-guice


On Oct 13, 1:10 pm, Martin Grajcar <grajc...@seznam.cz> wrote:
> Do you think it's bad idea?

Yeah, I don't think it pulls its weight. With the current solution,
you get to supply your own fallback value such as NoOpAirConditioner.
If we permitted optionality on a parameter-by-parameter basis, our
poor users would have to cope with null.

Geoff Little

unread,
Aug 30, 2017, 12:29:24 PM8/30/17
to google-guice
Does this remain the recommended way to deal with Optional constructor arguments?

Tavian Barnes

unread,
Aug 30, 2017, 2:14:34 PM8/30/17
to google-guice
I'd recommend using OptionalBinder in modern Guice.
Reply all
Reply to author
Forward
0 new messages