Java – how to declare the return type of a method as the return type of the last lambda in the array passed to the method

I ask for something that I think is impossible. If so, I will delete the problem

I have ways:

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

These functions are:

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
}

Abstract methods in these interfaces return different types of values I pass Lambdas to my convertby method

I want to set the convertby return type to be the same as the function return type [functions. Length – 1]

Is this possible?

Edit:

I have changed the signature of the method and the signature of the method in the interface It works, but only I project below the position of the main mark It only needs to cast strange things in three of the four method calls, and I want to get rid of coercion completely in the main part

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
}

Main methods:

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!

I don't understand why the compiler understands the content returned by sum, but does not infer the content returned by collectints, for example

Solution

It seems that you have some misunderstandings about the generic type hierarchy If you want to extend a generic type, you must make a basic decision about the actual type of the extended class or interface You can specify the exact type, for example

interface StringTransformer extends Function<String,String> {}

(here we create a type that extends a generic type but is not a generic type)

Alternatively, you can create a generic type that uses its own type parameters to specify the actual type parameters of the superclass:

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

Notice how we use our own constraints to create a new type parameter n and use it to parameterize the superclass to require its type parameters to match our type

In contrast, when you declare a class

interface FLines<T,R> extends Function

You are extending the original type function and creating a new type parameter < T, R > which is completely useless in your scenario

To keep the above examples, you can implement them as

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

And because they inherit methods of the correct type, you can use them to combine these functions:

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

By applying this to your scenario, you can define similar interfaces

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

And redesign your inputconverter to accept only one function that may be a composite function:

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

This can be used in a type safe manner:

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)
);
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>