Java 具有泛型形式Bean类的Spring ClassCastException
我试图使用一个泛型类作为Spring表单的支持bean,但当Spring框架试图将对象强制转换为实际类型时,最终会出现ClassCastException 提交表单时,尝试调用SrvRecord对象上的方法时发生以下错误(第105行,用注释标记): 表单Bean:Java 具有泛型形式Bean类的Spring ClassCastException,java,spring,generics,Java,Spring,Generics,我试图使用一个泛型类作为Spring表单的支持bean,但当Spring框架试图将对象强制转换为实际类型时,最终会出现ClassCastException 提交表单时,尝试调用SrvRecord对象上的方法时发生以下错误(第105行,用注释标记): 表单Bean: public class RecordBean<T> { private T original; private T modified; public RecordBean() {
public class RecordBean<T>
{
private T original;
private T modified;
public RecordBean()
{
super();
}
public RecordBean(T original)
{
this.original = original;
this.modified = original;
}
public T getOriginal()
{
return original;
}
public void setOriginal(T original)
{
this.original = original;
}
public T getModified()
{
return modified;
}
public void setModified(T modified)
{
this.modified = modified;
}
}
公共类RecordBean
{
私人T原件;
私有T修改;
公共记录bean()
{
超级();
}
公共记录bean(T原件)
{
this.original=原件;
修改后的=原件;
}
公共T getOriginal()
{
归还原件;
}
公共文件原件(T原件)
{
this.original=原件;
}
公共T getModified()
{
修改返回值;
}
公共无效设置已修改(T已修改)
{
this.modified=modified;
}
}
控制器方法:
@RequestMapping(value = "new", method = RequestMethod.GET)
public String add(Model model)
{
SrvRecord srvRecord = getSrvRecord();
RecordBean<SrvRecord> record = new RecordBean<SrvRecord>(srvRecord);
model.addAttribute("record", record);
return "generic/new";
}
@RequestMapping(value = "new", method = RequestMethod.POST)
public String add(Model model, @ModelAttribute("record") RecordBean<SrvRecord> record)
{
// Call a method on the SrvRecord object
doSomething(record.getModified().getZone().getName()); // line 105
doSomething(record.getOriginal().getZone().getName());
// ...
}
@RequestMapping(value=“new”,method=RequestMethod.GET)
公共字符串添加(模型)
{
SrvRecord SrvRecord=getSrvRecord();
RecordBean记录=新的RecordBean(srvRecord);
model.addAttribute(“记录”,记录);
返回“通用/新”;
}
@RequestMapping(value=“new”,method=RequestMethod.POST)
公共字符串添加(模型模型,@modeldattribute(“记录”)RecordBean记录)
{
//调用SrvRecord对象上的方法
doSomething(record.getModified().getZone().getName());//第105行
doSomething(record.getOriginal().getZone().getName());
// ...
}
视图:
任何想法或建议都很好。能够使用通用表单bean将从基线中消除大量不必要的代码
仅供参考,使用的Spring版本是3.0.6.0版本
谢谢,
Beau你可以试着让你的泛型更具体一些
public class RecordBean<T extends interfaceOrSuperclassOfSrvRecord>
公共类RecordBean
您可以尝试使您的泛型更加具体
public class RecordBean<T extends interfaceOrSuperclassOfSrvRecord>
公共类RecordBean
通过为类实现选中的泛型,即在对象中保留类
引用,并在必要时使用显式强制转换,您可以找到bug的来源:
public class RecordBean<T>
{
private Class<T> clazz;
private T original;
private T modified;
public RecordBean(Class<T> clazz)
{
super();
this.clazz = clazz;
}
public RecordBean(T original, Class<T> clazz)
{
this.clazz = clazz;
this.original = original;
this.modified = original;
}
public RecordBean(T original)
{
this(original, (Class<T>) original.getClass());
}
public T getOriginal()
{
return original;
}
public void setOriginal(T original)
{
this.original = clazz.cast(original);
}
public T getModified()
{
return modified;
}
public void setModified(T modified)
{
this.modified = clazz.cast(modified);
}
}
公共类RecordBean
{
私人课堂;
私人T原件;
私有T修改;
公共记录bean(类clazz)
{
超级();
this.clazz=clazz;
}
公共RecordBean(T原始,类clazz)
{
this.clazz=clazz;
this.original=原件;
修改后的=原件;
}
公共记录bean(T原件)
{
这个(original,(Class)original.getClass());
}
公共T getOriginal()
{
归还原件;
}
公共文件原件(T原件)
{
this.original=clazz.cast(原件);
}
公共T getModified()
{
修改返回值;
}
公共无效设置已修改(T已修改)
{
this.modified=clazz.cast(modified);
}
}
通过为类实现选中的泛型,即在对象中保留类
引用,并在必要时使用显式强制转换,您可以找到bug的来源:
public class RecordBean<T>
{
private Class<T> clazz;
private T original;
private T modified;
public RecordBean(Class<T> clazz)
{
super();
this.clazz = clazz;
}
public RecordBean(T original, Class<T> clazz)
{
this.clazz = clazz;
this.original = original;
this.modified = original;
}
public RecordBean(T original)
{
this(original, (Class<T>) original.getClass());
}
public T getOriginal()
{
return original;
}
public void setOriginal(T original)
{
this.original = clazz.cast(original);
}
public T getModified()
{
return modified;
}
public void setModified(T modified)
{
this.modified = clazz.cast(modified);
}
}
公共类RecordBean
{
私人课堂;
私人T原件;
私有T修改;
公共记录bean(类clazz)
{
超级();
this.clazz=clazz;
}
公共RecordBean(T原始,类clazz)
{
this.clazz=clazz;
this.original=原件;
修改后的=原件;
}
公共记录bean(T原件)
{
这个(original,(Class)original.getClass());
}
公共T getOriginal()
{
归还原件;
}
公共文件原件(T原件)
{
this.original=clazz.cast(原件);
}
公共T getModified()
{
修改返回值;
}
公共无效设置已修改(T已修改)
{
this.modified=clazz.cast(modified);
}
}
您可以在Spring上提交一个bug。问题在于Spring使用反射来确定参数类型,而忽略泛型,因此只是实例化一个没有泛型的普通RecordBean对象。因此,RecordBean中的对象只是作为对象创建的,无法将其强制转换为SrvRecord。唯一的解决办法是不要使用泛型
背景
Spring在内部使用MethodParameter类来读取方法参数。有一个方法叫做
public Class<?> getParameterType()
这段代码不带泛型地读取参数。他们需要打电话来妥善处理
this.method.getGenericParameterTypes()[this.parameterIndex]
后来的方法
HandlerMethodInvoker.resolveModelAttribute()
调用以通过执行以下操作实例化命令类
bindObject = BeanUtils.instantiateClass(paramType);
但是paramType的值是“com.test.RecordBean”,而不是预期的“com.test.RecordBean”您可以在Spring上提交一个bug。问题在于Spring使用反射来确定参数类型,而忽略泛型,因此只是实例化一个没有泛型的普通RecordBean对象。因此,RecordBean中的对象只是作为对象创建的,无法将其强制转换为SrvRecord。唯一的解决办法是不要使用泛型 背景 Spring在内部使用MethodParameter类来读取方法参数。有一个方法叫做
public Class<?> getParameterType()
这段代码不带泛型地读取参数。他们需要打电话来妥善处理
this.method.getGenericParameterTypes()[this.parameterIndex]
后来的方法
HandlerMethodInvoker.resolveModelAttribute()
调用以通过执行以下操作实例化命令类
bindObject = BeanUtils.instantiateClass(paramType);
但是paramType的值是“com.test.RecordBean”,而不是预期的“com.test.RecordBean”同样的问题在这里,我发现的唯一解决方案是为每个控制器创建一个额外的类(FormModelObjectCity),所以我的类如下所示:
public class CityDTO {
private Long id;
private String name;
public CityDTO() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
form.html,根据替换[]