Java 8 个通用 java.util.Function

Java 8 Generic java.util.Function

我正在学习 Java 8 中的 FunctionalInterface。在做了一些基本的函数示例之后,我尝试对 GenericType 参数做同样的事情。

public class Main {

    public enum LocType { 
        Area, Country
    }

    public <T> Function<T, T> getCreateFunction(LocType type) {

        AreaService areaService = new AreaService();
        CountryService countryService = new CountryService();
        switch(type) {
            case Area : return areaService::createArea;
            case Country : return countryService::createCountry;
            default : return null;
        }
    }

}

public class AreaService {

    public Area createArea(Area area) {
       // some logic
       return area;
    }

}

public class CountryService {

    public Country createCountry(Country country) {
        // some logic
        return country;
    }

}

// Area & Country are Model Classes

但是 eclipse 编译器抛出错误

The type AreaService does not define createArea(T) that is applicable here

不能在 FunctionalInterface 中定义通用类型参数吗?

可以定义泛型类型参数。您可以在 jdk 中找到示例,例如

andThen

default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t) -> after.apply(apply(t));
}

identity

static <T> Function<T, T> identity() {
    return t -> t;
}

在您的示例中不起作用的是 areaService::createAreacountryService::createCountry 是具体类型的 Functions

编译器无法将 Area 分配给泛型类型 T。因为 T 可以是任何东西,即 IntegerStream

您可以在此处使用 Class class 作为类型标记。 (我将忽略您发布的代码的一些明显问题,例如无法调用 new AreaService() 等)。不要为您希望函数创建(操作?)的事物类型定义枚举,而是使用 Class 作为参数:

@SuppressWarnings("unchecked")
public <T> Function<T, T> getCreateFunction(Class<T> type) {

    AreaService areaService = new AreaService();
    CountryService countryService = new CountryService();
    if (type == Area.class) {
        return t -> (T) areaService.createArea((Area)t);
    } else if (type == Country.class) {
        return t -> (T) countryService.createCountry((Country)t);
    }
    return null ; // may be better to throw an IllegalArgumentException("Unsupported type") 
}

现在您可以执行诸如

之类的操作
Main main = new Main();
Function<Area, Area> areaChanger = main.getCreateFunction(Area.class);
Function<Country, Country> countryChanger = main.getCreateFunction(Country.class);

它的工作方式是任何 class T 的 class 文字 T.classClass<T> 类型。所以 Area.class 的类型是 Class<Area>,而 Country.class 的类型是 Class<Country>.

因此,如果您调用 getCreateFunction(Area.class),编译器可以推断出 T 在该调用中是 Area,然后 return 类型是 Function<Area, Area> .另一方面,在 getCreateFunction 的实现中,虽然编译器只能推断 lambda 的参数是未知类型 T,但我们知道它 T 必须是参数表示的类型type;也就是说,如果 type==Area.class 我们可以安全地将 t 转换为 Area 并且(从 areaService.createArea 编辑的值 return)Area 转换为 T .因此转换是安全的(即使是转换为未知类型 T)。

如果您想进一步限制可以传递给 getCreateFunction(...) 的值,您可以定义一个标记接口:例如public interface Region { } 并使 AreaCountry 实现该接口。然后定义

public <T extends Region> Function<T,T> getCreateFunction(Class<T> type) {...}

并且只有为 class 实现(或扩展的接口)的实体传递 class 令牌才有效 Region.