'If I use field injection with Guice, why can I only use the no arg constructor?

Here is an example:

public class Dog implements Animal{
    private  String color;

    @Inject
    private  Owner owner;

    //This constructor always used to build the Dog object.
    public Dog(){}

    public Dog(String random){}
}

Is this a restriction or default behavior? Is there any way to use a parameterized constructor instead to build the Dog object? This seems like a limitation so I must be missing something.



Solution 1:[1]

Annotate your other constructor with @Inject

Think about it. Guice is a dependency injection (DI) framework. This means that Guice takes responsibility for creating objects.

Guice therefore needs to know some things. The first among them is how to create a new instance. Therefore, Guice (and most other DI frameworks) put some conventions about how to create new objects.

Guice's conventions for creating objects are the following: either provide a no-arg constructor or annotate it with @Inject. Why the no-arg constructor? Because all of its parameters are known: there are none. It's easy to create an object that doesn't have any parameter.

If there was any parameter, such as a String in your example, how would Guice know which String to inject? Well, you might say that you provide it in a module, fair enough. But in your example, you have more than one constructor. How would Guice know which constructor to use? Well, let's standardize and say that the easiest to construct is allowed but not the others. So let's instantiate using the no-arg constructor.

Please note that you can associate field injection with constructor injection, but to do so, you must annotate at most one constructor with @Inject. The following code is totally valid:

public class Dog implements Animal{
    private  String color;

    @Inject
    private  Owner owner;

    //This constructor always used to build the Dog object.
    public Dog(){}

    @Inject public Dog(String random){} // Note the @Inject annotation.
}

Please note that Guice's @Inject's Javadoc is rather explicit (emphasis mine):

The class being constructed must have exactly one of its constructors marked with @Inject or must have a constructor taking no parameters. The `Injector then proceeds to perform field and method injections.

Also, note the Javadoc of @javax.inject.Inject:

Injectable constructors are annotated with @Inject and accept zero or more dependencies as arguments. @Inject can apply to at most one constructor per class.

[...]

@Inject is optional for public, no-argument constructors when no other constructors are present. This enables injectors to invoke default constructors.

[...]

So to answer your question, no, it's not possible to request Guice to inject your constructor with a String argument without annotating it with @Inject.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Olivier Grégoire