Reputation: 307
I got a pretty simple question but couldn't find anything so far.
I'm trying to create two class constructors.
The first constructor gets 2 Strings and one HashMap and initializes the class variables.
public Foo(String a, String b, HashMap<String, String> c) {
this.a = a;
this.b = b;
this.c = c;
}
The second constructor should only get the 2 Strings and create a "default"-HashMap.
Usually you just call this()
with the default-value inside but I could not find a way to do this with a HashMap
.
public Foo(String a, String b) {
this(a, b, new HashMap<String, String>().put("x", "y").put("f","g"));
}
Eclipse marks an error:
Type mismatch: cannot convert from
String
toHashMap<String,String>
And otherwise the this()
-call cannot be the first statement in the function.
public Foo(String a, String b) {
HashMap<String, String> c = new HashMap<String, String>();
c.put("x", "y");
c.put("f", "g");
this(a, b, c);
}
Any ideas how to solve this?
Worst case I had to duplicate the code, but I was wondering if there is no better way.
Upvotes: 3
Views: 2702
Reputation: 12440
You can work around the "call to this() must be the first statement" by adding a static method that creates your default Map
instance:
public Foo(String a, String b) {
this(a, b, createDefaultMap());
}
private static Map<String, String> createDefaultMap() {
Map<String, String> defaultMap = new HashMap<String, String>();
defaultMap.put("x", "y");
defaultMap.put("f", "g");
return defaultMap;
}
It is mandatory that createDefaultMap()
is static, as you may not access the half-constructed instance at this point.
Upvotes: 0
Reputation: 137184
If this Map is a constant, you could store it as a constant and reuse it. This avoids recreation of the Map each time a new Foo
is created but it is then shared across all Foo
s.
public class Foo {
private static final Map<String, String> DEFAULT = new HashMap<>();
static {
DEFAULT.put("x", "y");
DEFAULT.put("f","g");
}
public Foo(String a, String b) {
this(a, b, DEFAULT);
}
public Foo(String a, String b, Map<String, String> c) {
this.a = a;
this.b = b;
this.c = c;
}
}
You could also create a static method returning the correct value. Note that the method needs to be static because you can't call an instance method inside this()
.
public class Foo {
public Foo(String a, String b) {
this(a, b, getDefaultMap());
}
public Foo(String a, String b, Map<String, String> c) {
this.a = a;
this.b = b;
this.c = c;
}
private static Map<String, String> getDefaultMap() {
Map<String, String> map = new HashMap<>();
map.put("x", "y");
map.put("f", "g");
return map;
}
}
Upvotes: 5
Reputation: 1375
You can do a trick like this:
public Foo(String a, String b) {
this(a, b, new HashMap<String, String>(){
{
put("x", "y");
put("f", "g");
}
});
}
It creates anonymous class that inherits HashMap and defines init block with putting values.
Upvotes: 0
Reputation: 7357
It´s unneccessary to create a local variable of c
.
You could simply call it like this.
public Foo(String a, String b) {
this(a, b, new HashMap<String, String>());
c.put("x", "y");
c.put("f", "g");
}
Since your other constructor this(String, String, HashMap<String, String>())
will assign the new HashMap
to c
invoking methods on c
will also fill this newly created HashMap
and will assign the default values that you did provide to it.
Another solution could be to create a static method and just call it
public static HashMap<String, String> createDefaultHashMap() {
HashMap<String, String> c = new HashMap<String, String>();
c.put("x", "y");
c.put("f", "g");
return c;
}
public Foo(String a, String b) {
this(a, b, Foo.createDefaultHashMap());;
}
Upvotes: 4
Reputation: 100
The HashMap
method .put
returns a String
so you are passing a String
when calling the 3 argument constructor in your 2 argument constructor.
Upvotes: 1