我要求我看不到的东西,如果是的话,我会删除问题。
我有方法:
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[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> extends Function<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, flines, join, collectInts);//works without cast!
我不明白为什么编译器会理解sum
返回的内容,但不会推断实例collectInts
返回的内容。
答案 0 :(得分:4)
看来,你对泛型类型层次结构有一些误解。如果要扩展泛型类型,则必须对扩展类或接口的实际类型做出基本决策。您可以指定精确类型,如
interface StringTransformer extends Function<String,String> {}
(这里我们创建一个扩展泛型类型但不是通用类型的类型)
或者您可以创建一个泛型类型,它使用自己的类型参数来指定超类的实际类型参数:
interface NumberFunc<N extends Number> extends Function<N,N> {}
注意,我们如何使用自己的约束创建一个新的类型参数N
,并使用它来参数化超类以要求其类型参数与我们的匹配。
相反,当您声明类似
的类时interface FLines<T, R> extends Function
您正在扩展原始类型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)
);
答案 1 :(得分:2)
您必须更改方法签名并将内联最后一个vararg值更改为单独的参数。
如果您将此参数作为最后一个参数,那么您将无法使用vararg参数,因为它始终是最后一个参数,并且必须表示为数组,以防它不是最后一个:
public <T, R> R convertBy(Function[] functions, Function<T, R> special) { }
但是,如果您坚持使用varargs,那么您可以移动&#34;特殊&#34; Function
作为第一个参数:
public <T, R> R convertBy(Function<T, R> special, Function... functions) { }
答案 2 :(得分:1)
感谢所有详细阐述这个主题的人,你的解决方案在现实世界中要好得多。
作为作者,我想发布我的解决方案,该解决方案不能将convertBy()
的调用更改为main()
一位。它很短而且很丑,但很有效。
Main
:
Function<String, List<String>> flines ... lambda here
Function<List<String>, String> join ... lambda here
Function<String, List<Integer>> collectInts ... lambda here
Function<List<Integer>, Integer> sum ... lambda here
String fname = System.getProperty("user.home") + "/LamComFile.txt";
InputConverter<String> fileConv = new InputConverter<>(fname);
List<String> lines = fileConv.convertBy(flines);
String text = fileConv.convertBy(flines, join);
List<Integer> ints = fileConv.convertBy(flines, join, collectInts);
Integer sumints = fileConv.convertBy(flines, join, collectInts, sum);
System.out.println(lines);
System.out.println(text);
System.out.println(ints);
System.out.println(sumints);
List<String> arglist = Arrays.asList(args);
InputConverter<List<String>> slistConv = new InputConverter<>(arglist);
sumints = slistConv.convertBy(join, collectInts, sum);
System.out.println(sumints);
InputConverter
类:
public class InputConverter<T> {
private T value;
public InputConverter(T value) {
this.value = value;
}
public <T, R> R convertBy(Function... functions) {
Object result = value;
for (int i = 0; i < functions.length; i++) {
result = functions[i].apply(result);
}
return (R) result;
}
}