Reputation: 17775
When I try to declare this simple bean:
<bean id="file" class="java.io.File" c:child="foo.txt" c:parent="\tmp" />
I get:
Unsatisfied dependency expressed through constructor argument with index 0 of type [java.io.File]: Ambiguous constructor argument types - did you specify the correct bean references as constructor arguments?
Ok, ok... I get it. I can try to use indexes on my constructor arg. I see that as the de facto answer. What I don't get, is if I have a similar class (for demonstration):
public class MultipleConstructors {
private String a;
private String b;
private int c;
private Object d;
public MultipleConstructors(String a, String b) {
this(a, b, -1, null);
}
public MultipleConstructors(String a, String b, int c) {
this(a, b, c, null);
}
public MultipleConstructors(String a, String b, int c, Object d) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
}
I can in fact declare it in the same way as the File declaration and Spring let's me. Both of these work... but why?
<bean
id="multipleConstructors1"
class="sandbox.spring.MultipleConstructors"
c:a="testing"
c:b="testing, hello"
c:c="123"/>
<bean
id="multipleConstructors2"
class="sandbox.spring.MultipleConstructors"
c:a="testing"
c:b="testing, hello"
/>
Is it because the File class is not instrumented somehow? e.g. MultipleConstructors is a local source file, vs. the other is in the jdk?
Upvotes: 0
Views: 1565
Reputation: 279950
Is it because the File class is not instrumented somehow
Yes. The JDK was probably compiled in a way that did not preserve the parameter names. You can confirm this by running, for example,
System.out.println(Arrays.toString(File.class.getConstructor(String.class, String.class).getParameters()));
If this prints
[java.lang.String arg0, java.lang.String arg1]
then the parameter names are not present in the .class
file used to run your program.
The parameter names are therefore not available to Spring and so these two
c:child="foo.txt" c:parent="\tmp"
can't be mapped reliably to the underlying parameters. Spring can convert from a String
value to a File
object, so two File
constructors are applicable. Spring can't choose which one to use.
This is not the case with your own class, which you're probably compiling in a way that preserves the parameter names. Or if you're not, then the arguments you've provided deterministically map to a constructor.
For example, only one constructor can be applied to
c:a="testing"
c:b="testing, hello"
c:c="123"
this one
public MultipleConstructors(String a, String b, int c) {
and only one can be applied to
c:a="testing"
c:b="testing, hello"
this one
public MultipleConstructors(String a, String b) {
Upvotes: 2