Reputation: 1256
I have 2 constructors for a class. A parametrized constructor and a non parametrized one. The problem is I am unable to invoke the parametrized one from the other using this(...). However it works when I try the same invocation from somewhere else (say a main method)
Here is the code
package com.test.generics;
public class Key<T> {
private T t;
public Key(T t){
this.t = t;
}
public T getKey(){
return t;
}
}
And then
package com.test.generics;
public class KeyValueObject<T> {
private String value;
private Key<T> key;
public KeyValueObject(Key<T> k){
key = k;
value = "-1";
}
public KeyValueObject(String keyString){
this(new Key<String>(keyString)); //Here is the problem, this says the Constructor KeyValueObject<T>(Key<String> k) is undefined
}
public static void main(String[] args) {
Key<String> keyStr = new Key<String>("x");
KeyValueObject<String> keyValObj = new KeyValueObject<String>(keyStr); //I try the same thing from main method and it works.
}
}
Why does the compiler say "Constructor KeyValueObject(Key k) is undefined". I do have a constructor KeyValueObject(Key k) defined.
Also in the main method, I am pretty much doing the same thing. If the overloaded constructor had worked, I could have used new KeyValueObject("x")
Upvotes: 1
Views: 62
Reputation: 15
The type Key<String>
does not necessarily match Key<T>
so the error is valid. (an unsafe typecast would be possible thought)
consider implementing a factory method like this:
public static KeyValueObject<String> createKeyValueObject(final String keyString) {
return new KeyValueObject<String>(new Key<String>(keyString));
}
or for better use of the generic possibilities:
public KeyValueObject(T k) {
this(new Key<T>(k));
}
Upvotes: 1
Reputation: 3048
As I already wrote in the comment, you can do this:
public class Program {
public static void main(String[] args) {
KeyValueObject<String> $0 = new KeyValueObject<>(new Key<>("x")); //old school
KeyValueObject<String> $1 = new KeyValueObject<>("x"); //boxing constructor
KeyValueObject<String> $2 = KeyValueObject.make("x"); //factory method
}
}
class Key<T> {
T key;
public Key(T key){
this.key = key;
}
public T getKey(){
return key;
}
}
class KeyValueObject<T> {
//Solution 2: Create a factory method to handle the case `T` == `String`
static KeyValueObject<String> make(String value) {
return new KeyValueObject<>(value);
}
String value;
Key<T> key;
KeyValueObject(Key<T> key){
this.key = key;
this.value = "-1";
}
//Solution 1: Change `String` to `T`
KeyValueObject(T key){
this(new Key<>(key));
}
}
Upvotes: 1
Reputation: 1890
The declared type for the KeyValueObject<T>
attribute:
private Key<T> key;
is different from the type argument in your constructor call:
public KeyValueObject(String keyString){
this(new Key<String>(keyString));
}
The constructor's generic type argument must match with the attribute's type:
public KeyValueObject(T t){
this(new Key<T>(t));
}
Upvotes: 3
Reputation: 16380
The compiler error is justified, because the code is not type safe. To see why, suppose you wrote:
KeyValueObject<Integer> kv = new KeyValueObject("not an Integer");
The above would produce an attempt to invoke KeyValueObject<Integer>(Key<Integer>)
with a Key<String>
argument, which would obviously not be valid.
Upvotes: 1