我是一个java泛型的初学者,我尝试在类中使用泛型来解析我的user.yaml文件。当我尝试解析yaml文件时,我得到 * 类型变量'T'无法解析 * 不确定我哪里出错了。
最初这只是一个普通的类,然后我实现了泛型。
my yaml file
user:
name: Test User
age: 30
public interface IUser {
String getName();
IUser setName(String name);
Integer getAge();
IUser setAge(Integer age);
}
public class User implements IUser{
@JsonProperty("name")
private String name;
@JsonProperty("age")
private Integer age;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
@JsonProperty("name")
public String getName() {
return name;
}
@JsonProperty("name")
public User setName(String name) {
this.name = name;
return this;
}
@JsonProperty("age")
public Integer getAge() {
return age;
}
@JsonProperty("age")
public User setAge(Integer age) {
this.age = age;
return this;
}
@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
@Override
public String toString() {
return new ToStringBuilder(this).append("name", name).append("age", age).append("additionalProperties", additionalProperties).toString();
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(additionalProperties).append(age).append(name).toHashCode();
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if ((other instanceof User) == false) {
return false;
}
User rhs = ((User) other);
return new EqualsBuilder().append(additionalProperties, rhs.additionalProperties).append(age, rhs.age).append(name, rhs.name).isEquals();
}
}
public interface IExample {
<T extends IUser> T getUser();
<T extends IUser> void setUser(T user);
}
public class Example implements IExample{
@JsonProperty("user")
private User user;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
@JsonProperty("user")
public <T extends IUser> T getUser() {
return (T) user;
}
@JsonProperty("user")
public <T extends IUser> void setUser(T t) {
this.user = (User)t;
}
@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
@Override
public String toString() {
return new ToStringBuilder(this).append("user", user).append("additionalProperties", additionalProperties).toString();
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(additionalProperties).append(user).toHashCode();
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if ((other instanceof Example) == false) {
return false;
}
Example rhs = ((Example) other);
return new EqualsBuilder().append(additionalProperties, rhs.additionalProperties).append(user, rhs.user).isEquals();
}
}
my main class where i'm trying to parse yaml object
public class ReadYaml {
public void parse(){
String path = "path/to/user.yaml";
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
try {
IExample example = mapper.readValue(new File(path), Example.class);
System.out.println(example.getUser().getName());
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
new ReadYaml().parse();
}
}
我希望输出为:* 测试用户 ,但实际输出为 * com. fasterxml. jackson. databind. JsonMappingException:无法解析类型变量'T'(具有类com.yaml.Example的上下文)
更新
updated yaml file
user:
name: Test User
age: 30
address:
line1: bangalore
line2: karnataka
public interface IAddress {
String getLine1();
IAddress setLine1(String line1);
String getLine2();
IAddress setLine2(String line2);
}
public class Address implements IAddress {
// code getters and setters
}
public interface IExample<T, U extends IUser & IAddress> {
T getUser();
void setUser(T user);
U getAddress();
void setAddress(U address);
}
public class Example<T, U extends IUser & IAddress> implements IExample<T, U>{
now i'm trying to parse yaml file.
public class ReadYaml {
.
.
.
TypeReference<Example<User, Address> typeReference = new TypeReference<Example<User, Address>() {
};
IExample example = mapper.readValue(new File(path), typeReference);
System.out.println(example.getAddress.getLine1());
TypeReference<Example<User, Address> typeReference
声明中出现错误:类型参数"Address"不在其界限内,应实现"IUser"
1条答案
按热度按时间wfsdck301#
由于java's type erasure,您的代码有2个问题;这要求Jackson知道在反序列化数据时要使用的所有具体类型。在泛型类型的情况下,它需要知道要使用的泛型类的界限(参数化类型的具体类)。Jackson通过类型引用被告知该界限;你需要提供的。那么你有两个问题:
1.据我所知,Jackson无法获知泛型方法的边界(这没有多大意义),因此,在
Example
中,属性user
(public <T extends IUser> void setUser(T t)
)代表了一个障碍,因为Jackson无法知道使用哪个T
进行反序列化/写入。1.当调用
mapper.readValue
时,需要显式地通知Jackson要读入的类型(包括有界类型);这是缺少的(您只是使用Example.class
):因此,要解决这些问题,你需要改变:
1.在
IExample/Example
中将泛型方法替换为泛型类:1.通过传递适当的jackson
TypeReference
来通知JacksonExample
有界类型:增编:
您发现的新问题,关于额外的泛型类型
IAddress/Address
;不在TypeReference
附近,您将其正确设置为:问题在于接口和类中泛型类型的声明。
当您说
U extends IUser & IAddress
时,您是在说U
扩展/实现了两者IUser
和IAddress
;这就是为什么Jackson抱怨Address
没有扩展IUser
;因为它只扩展IAddress
。另外,T
将被隐式地约束为能够绑定到扩展java.lang.Object
的任何类(而不是IUser
;这可能是您所期望的),因为您没有为它指定extends...
。因此,要解决此问题,请替换
IExample
和Example
的泛型类型声明:与
Complete code on GitHub