Java 8 Generic java.util.Function

时间:2016-07-26 20:20:40

标签: java generics java-8 functional-interface

我正在学习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中定义通用类型参数..?

2 个答案:

答案 0 :(得分:3)

您可以在此处使用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);

现在你可以做一些事情,比如

T.class

这样做的方式是任何类T的类文字Class<T>都是Area.class类型。因此Class<Area>的类型为Country.class,而Class<Country>的类型为getCreateFunction(Area.class)

因此,如果您调用T,编译器可以在该调用中推断出AreaFunction<Area, Area>,然后返回类型为getCreateFunction。另一方面,在T的实现中,虽然编译器只能推断lambda的参数是未知类型T,但我们知道它type必须属于由参数type==Area.class表示的类型;即如果t,我们可以安全地将Area投放到areaService.createArea和(AreaT返回的值T。因此,演员阵容是安全的(甚至是演员到未知类型getCreateFunction(...))。

如果您想进一步限制可传递给public interface Region { }的值,您可以定义标记界面:例如Area并使Countrypublic <T extends Region> Function<T,T> getCreateFunction(Class<T> type) {...} 实现该接口。然后定义

Region

只有为实现的类(或扩展的接口)app.controller('MainController', ['$scope',function(a){ 传递类令牌才有效。

答案 1 :(得分:0)

可以定义泛型类型参数。你可以在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