Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使双消费者接受对象_Java - Fatal编程技术网

Java 使双消费者接受对象

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-

我有一个JTable TableModel的列定义列表,其中列“B”有一个setter BiConsumer,它接受一个BauwerkOption类和一个字符串

当我尝试将字符串设置为“…接受…”行时,会出现以下错误:

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);
    }
}