加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 如何将方法的返回类型声明为传递给方法的数组中最后一个

发布时间:2020-12-14 05:53:58 所属栏目:Java 来源:网络整理
导读:我要求一些我认为不可能的东西,如果是的话,我会删除问题. 我有方法: public Object convertBy(Function... functions) {} 这些功能是: interface FLines extends Function { @Override default Object apply(Object t) { return null; }; public ListStrin
我要求一些我认为不可能的东西,如果是的话,我会删除问题.

我有方法:

public Object convertBy(Function... functions) {
}

这些功能是:

interface FLines extends Function {
    @Override
    default Object apply(Object t) {
        return null;
    };

    public List<String> getLines(String fileName);
}

interface Join extends Function {
    @Override
    default Object apply(Object t) {
        return null;
    };

    public String join(List<String> lines);//lines to join
}

interface CollectInts extends Function {
    @Override
    default Object apply(Object t) {
        return null;
    };

    public List<Integer> collectInts(String s);
}

interface Sum<T,R> extends Function<T,R> {
    @Override
    default Object apply(Object t) {
        return null;
    };

    public R sum(T list);//list of Integers
}

这些接口中的抽象方法返回不同类型的值.我将lambdas传递给我的convertBy方法.

我想设置convertBy返回类型与函数的返回类型[functions.length – 1]相同.

这有可能吗?

编辑:

我已经改变了方法的签名和界面内方法的签名.它工作,但只有我在主要标记的位置投射在下面.它只需要在4个方法的调用中的3个中投射出奇怪的东西,我想在主要部分中完全摆脱强制转换.

import java.util.List;
import java.util.function.Function;


public class InputConverter<T> {

    private T value;

    public InputConverter(T value) {
        this.value = value;
    }


    public <T,R> R convertBy(Function<T,R> special,Function... functions) { 
        if (functions.length == 0) {
            FLines flines = (FLines) special;
            return (R) flines.getLines((value instanceof String) ? (String) value : null);
        } else if (functions.length == 1) {
            FLines flines = (FLines) functions[0];
            Join join = (Join) special;
            return (R) join.join(flines.getLines((String) value));
        } else if (functions.length == 2) {
            if (functions[0] instanceof FLines) {
                FLines flines = (FLines) functions[0];
                Join join = (Join) functions[1];
                CollectInts collectInts = (CollectInts) special;
                return (R) collectInts.collectInts(join.join(flines.getLines((String) value)));
            } else {
                Join join = (Join) functions[0];
                CollectInts collectInts = (CollectInts) functions[1];
                Sum sum = (Sum) special;
                return (R) sum.sum(collectInts.collectInts(join.join((List<String>) value)));
            }
        } else {
            FLines flines = (FLines) functions[0];
            Join join = (Join) functions[1];
            CollectInts collectInts = (CollectInts) functions[2];
            Sum sum = (Sum) special;
            return (R) sum.sum(collectInts.collectInts(join.join(flines.getLines((String) value))));
        }
    }

    /*  public Integer convertBy(Join join,CollectInts collectInts,Sum sum) {
            return sum.sum(collectInts.collectInts(join.join((List<String>) value)));
        }*/

}

interface FLines<T,R> extends Function {
    @Override
    default Object apply(Object t) {
        return null;
    };
    public R getLines(T fileName);
//  public List<String> getLines(String fileName);
}

interface Join<T,R> extends Function {
    @Override
    default Object apply(Object t) {
        return null;
    };
    public R join(T lines);//lines to join
//  public String join(List<String> lines);//lines to join
}

interface CollectInts<T,R> extends Function {
    @Override
    default Object apply(Object t) {
        return null;
    };
    public R collectInts(T t);
//  public List<Integer> collectInts(String s);
}

interface Sum<T,R> {
    @Override
    default Object apply(Object t) {
        return null;
    };

    public R sum(T list);//list of Integers
}

主要方法:

FLines<String,List<String>> flines ....

  Join<List<String>,String> join ...
  CollectInts<String,List<Integer>> collectInts ...

    Sum<List<Integer>,Integer> sum ...

String fname =/* System.getProperty("user.home") + "/*/ "LamComFile.txt"; 
InputConverter<String> fileConv = new InputConverter<>(fname);
List<String> lines =  fileConv.convertBy(flines);//cannot cast from Object to List<String>
String text =  fileConv.convertBy( join,flines);//cannot cast from Object to String
List<Integer> ints =   fileConv.convertBy(collectInts,flines,join);//cannot cast from Object to List<Integer>
Integer sumints =  fileConv.convertBy(sum,join,collectInts);//works without cast!

我不明白为什么编译器理解sum返回的内容,但不推断例如collectInts返回的内容.

解决方法

看起来,你对泛型类型层次结构有一些误解.如果要扩展泛型类型,则必须对扩展类或接口的实际类型做出基本决策.您可以指定精确类型,例如
interface StringTransformer extends Function<String,String> {}

(这里我们创建一个扩展泛型类型但不是泛型的类型)

或者您可以创建一个泛型类型,它使用自己的类型参数来指定超类的实际类型参数:

interface NumberFunc<N extends Number> extends Function<N,N> {}

注意,我们如何使用自己的约束创建一个新的类型参数N,并使用它来参数化超类以要求其类型参数匹配我们的类型.

相比之下,当你声明一个类时

interface FLines<T,R> extends Function

您正在扩展原始类型函数并创建新类型参数< T,R>在你的场景中完全没用.

要保留上面的示例,您可以将它们实现为

StringTransformer reverse = s -> new StringBuilder(s).reverse().toString();
NumberFunc<Integer> dbl = i -> i*2;

并且由于它们继承了正确类型的方法,您可以使用它们来组合这些函数:

Function<String,Integer> f = reverse.andThen(Integer::valueOf).andThen(dbl);
System.out.println(f.apply("1234"));

将此应用于您的场景,您可以定义类似的接口

interface FLines extends Function<String,List<String>> {
    @Override default List<String> apply(String fileName) {
        return getLines(fileName);
    }        
    public List<String> getLines(String fileName);
}
interface Join extends Function<List<String>,String> {
    @Override default String apply(List<String> lines) {
        return join(lines);
    }
    public String join(List<String> lines);
}
interface CollectInts extends Function<String,List<Integer>> {
    @Override default List<Integer> apply(String s) {
        return collectInts(s);
    }
    public List<Integer> collectInts(String s);
}
interface Sum extends Function<List<Integer>,Integer> {
    @Override default Integer apply(List<Integer> list) {
        return sum(list);
    }
    public Integer sum(List<Integer> list);
}

并重新设计您的InputConverter只接受一个可能是组合函数的函数:

public class InputConverter<T> {

    private T value;

    public InputConverter(T value) {
        this.value = value;
    }
    public <R> R convertBy(Function<? super T,? extends R> f) {
        return f.apply(value);
    }
}

这可以以类型安全的方式使用:

FLines flines = name -> {
    try { return Files.readAllLines(Paths.get(name)); }
    catch(IOException ex) { throw new UncheckedIOException(ex); }
};
Join join = list -> String.join(",",list);
CollectInts collectInts=
    s -> Arrays.stream(s.split(",")).map(Integer::parseInt).collect(Collectors.toList());
Sum sum = l -> l.stream().reduce(0,Integer::sum);

InputConverter<String> fileConv = new InputConverter<>("LamComFile.txt");
List<String> lines = fileConv.convertBy(flines);
String text = fileConv.convertBy(flines.andThen(join));
List<Integer> ints = fileConv.convertBy(flines.andThen(join).andThen(collectInts));
Integer sumints = fileConv.convertBy(
    flines.andThen(join).andThen(collectInts).andThen(sum)
);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读