Java 使双消费者接受对象
我有一个JTable TableModel的列定义列表,其中列“B”有一个setter BiConsumer,它接受一个BauwerkOption类和一个字符串 当我尝试将字符串设置为“…接受…”行时,会出现以下错误:Java 使双消费者接受对象,java,Java,我有一个JTable TableModel的列定义列表,其中列“B”有一个setter BiConsumer,它接受一个BauwerkOption类和一个字符串 当我尝试将字符串设置为“…接受…”行时,会出现以下错误: The method accept(Selektierung.BauwerkOption, capture#4-of ? extends Object) in the type BiConsumer<Selektierung.BauwerkOption,capture#4-
The method accept(Selektierung.BauwerkOption, capture#4-of ? extends Object) in the type BiConsumer<Selektierung.BauwerkOption,capture#4-of ? extends Object> is not applicable for the arguments (Selektierung.BauwerkOption, Object)
BiConsumer类型中的方法accept(Selektierung.BauwerkOption,capture#4-of?extends Object)不适用于参数(Selektierung.BauwerkOption,Object)
我的代码有什么问题?我想做的事有可能吗
public class TableModelSelektierung extends DefaultTableModel {
private static final long serialVersionUID = -5921626198599251183L;
private List<BauwerkOption> data;
private static List<ColDef<BauwerkOption, ? extends Object>> DEF = new ArrayList<>();
static {
DEF.add(new ColDef<BauwerkOption, String>("A", (o) -> o.getBauwerkstyp()));
DEF.add(new ColDef<BauwerkOption, String>("B", (o) -> o.getBezeichnung())
.withSetValueAtFunction((i, o) -> i.setBauwerkstyp(o)));
DEF.add(new ColDef<BauwerkOption, String>("C", (o) -> o.getNutzungsart()));
DEF.add(new ColDef<BauwerkOption, Double>("D", (o) -> o.getDurchmesser()));
}
@Override
public int getColumnCount() {
return DEF.size();
}
@Override
public boolean isCellEditable(int row, int column) {
return DEF.get(row).getValueSetterFunction() == null;
}
@Override
public int getRowCount() {
if (data != null) {
return data.size();
}
return 0;
}
@Override
public String getColumnName(int column) {
return DEF.get(column).getTitle();
}
public void setData(List<BauwerkOption> data) {
this.data = data;
fireTableDataChanged();
}
public BauwerkOption getObjectAt(int row) {
return data.get(row);
}
@Override
public void setValueAt(Object aValue, int row, int column) {
if (DEF.get(column).getValueSetterFunction() != null) {
DEF.get(column).getValueSetterFunction().accept(getObjectAt(row), aValue);
}
}
@Override
public Object getValueAt(int row, int column) {
BauwerkOption o = getObjectAt(row);
return DEF.get(column).getValueGetterFunction().apply(o);
}
}
class ColDef<InputObjekt, OutputValue> {
private String title;
private Function<InputObjekt, OutputValue> valueGetterFunction;
private BiConsumer<InputObjekt, OutputValue> valueSetterFunction;
public ColDef(String title, Function<InputObjekt, OutputValue> valueGetterFunction) {
this.title = title;
this.valueGetterFunction = valueGetterFunction;
}
public ColDef<InputObjekt, OutputValue> withSetValueAtFunction(BiConsumer<InputObjekt, OutputValue> valueSetterFunction) {
this.valueSetterFunction = valueSetterFunction;
return this;
}
public Function<InputObjekt, OutputValue> getValueGetterFunction() {
return valueGetterFunction;
}
public String getTitle() {
return title;
}
public BiConsumer<InputObjekt, OutputValue> getValueSetterFunction() {
return valueSetterFunction;
}
}
class BauwerkOption {
public BauwerkOption() {
}
public String getBezeichnung() {
return "";
}
public String getBauwerkstyp() {
return "";
}
public Double getDurchmesser() {
return 0d;
}
public String getNutzungsart() {
return "todo";
}
public void setBauwerkstyp(String s) {
}
}
公共类TableModelSelektierung扩展了DefaultTableModel{
私有静态最终长serialVersionUID=-5921626198599251183L;
私人名单数据;
私有静态列表DEF=newarraylist();
静止的{
添加(新的ColDef(“A”,(o)->o.getBauwerkstyp());
添加(新的ColDef(“B”,(o)->o.getBezeichnung())
.使用SetValueAtFunction((i,o)->i.setBauwerkstyp(o));
DEF.add(新的ColDef(“C”,(o)->o.getNutzungsart());
DEF.add(新的ColDef(“D”,(o)->o.getdurchesser());
}
@凌驾
public int getColumnCount(){
返回DEF.size();
}
@凌驾
公共布尔值可编辑(int行,int列){
返回DEF.get(行).getValueSetterFunction()==null;
}
@凌驾
public int getRowCount(){
如果(数据!=null){
返回data.size();
}
返回0;
}
@凌驾
公共字符串getColumnName(int列){
返回DEF.get(column.getTitle();
}
公共无效设置数据(列表数据){
这个数据=数据;
fireTableDataChanged();
}
公共BauwerkOption getObjectAt(国际行){
返回数据.get(行);
}
@凌驾
public void setValueAt(对象有效、整行、整列){
if(DEF.get(column).getValueSetterFunction()!=null){
DEF.get(column.getValueSetterFunction().accept(getObjectAt(row),aValue);
}
}
@凌驾
公共对象getValueAt(int行,int列){
BauwerkOption o=getObjectAt(行);
返回DEF.get(column.getValueGetterFunction().apply(o);
}
}
冷门{
私有字符串标题;
私有函数valueGetterFunction;
私人双消费者价值设定功能;
public ColDef(字符串标题、函数值getterfunction){
this.title=标题;
this.valueGetterFunction=valueGetterFunction;
}
带有SetValueAtFunction(双消费者valueSetterFunction)的公共函数{
this.valueSetterFunction=valueSetterFunction;
归还这个;
}
公共函数getValueGetterFunction(){
返回值getterfunction;
}
公共字符串getTitle(){
返回标题;
}
公共双消费者getValueSetterFunction(){
返回值设置函数;
}
}
BauwerkOption类{
公共BauwerkOption(){
}
公共字符串getBezeichnung(){
返回“”;
}
公共字符串getBauwerkstyp(){
返回“”;
}
公共双getdurchesser(){
返回0d;
}
公共字符串getNutzungsart(){
返回“待办事项”;
}
公共void setBauwerkstyp(字符串s){
}
}
问题在于ColDef#getValueSetterFunction()
。这将返回一个BiConsumer
,其中问号表示从对象扩展而来的某种类型。无法知道这是哪种特定类型,但它肯定不是对象
本身。因此,将Object
类型的值传递给TableModelSelektierung#setValueAt()
中的accept
方法将失败:
incompatible types: java.lang.Object cannot be converted to capture#1 of ?
信息
The method accept(Selektierung.BauwerkOption, capture#4-of ? extends Object) in the type BiConsumer<Selektierung.BauwerkOption,capture#4-of ? extends Object> is not applicable for the arguments (Selektierung.BauwerkOption, Object)
界面可以是这样的
public interface ColDefValue<T> {
T getValue();
}
由于无法更改setValueAt
中对象参数的类型,因此没有干净的方法来执行此操作
如果更换以下代码,它将尽可能干净:
这只是为了方便(您不需要自己的Lambda):
将泛型保持在适当的位置,但可以绕过继承时得到的对象限制。您可能应该在setValueAt中添加类型检查,以确保对象参数的类型正确。我添加了BauwerkOption类,但我忘记了…BiConsumerI不明白您在尝试什么say@user489872谢谢你让我们(克里斯和我)都高兴:-我认为这是最好的解决方案:没有解决办法吗?我是否必须传递一个对象类而不是在ColDef中定义的对象?不一定。问题的要点在于列表DEF
。正如Chris的回答所说,您可以切换到列表DEF
,这将把错误转移到此列表本身。列表的类型相同。一旦你试图解决这个问题,你就会以这样或那样的方式失去类型安全性。这不就是把问题转移到另一个地方(ColfDefXXValue类的构造函数)吗?也许是转移到另一个地方,不一定是在构造函数中。构造函数应该如下所示ColDefStringValue(字符串值)
public interface ColDefValue<T> {
T getValue();
}
private static List<ColDef<BauwerkOption, IColDefValue<?>>> DEF = new ArrayList<>();
private static List<ColDef<BauwerkOption, ?>> DEF = new ArrayList<>();
static {
DEF.add(new ColDef<BauwerkOption, String>("A", BauwerkOption::getBauwerkstyp));
DEF.add(new ColDef<BauwerkOption, String>("B", BauwerkOption::getBezeichnung).withSetValueAtFunction(BauwerkOption::setBauwerkstyp));
DEF.add(new ColDef<BauwerkOption, String>("C", BauwerkOption::getNutzungsart));
DEF.add(new ColDef<BauwerkOption, Double>("D", BauwerkOption::getDurchmesser));
}
@SuppressWarnings("unchecked")
public BiConsumer<InputObjekt, Object> getObjectValueSetterFunction() {
return (BiConsumer<InputObjekt, Object>) valueSetterFunction;
}
@Override
public void setValueAt(Object aValue, int row, int column) {
if (DEF.get(column).getValueSetterFunction() != null) {
DEF.get(column).getObjectValueSetterFunction().accept(getObjectAt(row), aValue);
}
}