4

我正在了解FunctionalInterfaceJava 8 中存在哪些。在做了一些基本的功能示例之后,我尝试对 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 中定义泛型类型参数吗?

4

2 回答 2

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都是 type Class<T>Area.class有 type ,Class<Area>Country.class有 type Class<Country>

因此,如果您调用getCreateFunction(Area.class),编译器可以推断该调用TArea的那个,并且返回类型是 then Function<Area, Area>。另一方面,在 的实现中getCreateFunction,虽然编译器只能推断 lambda 的参数是未知类型T,但我们知道它T必须是参数所代表的类型type;即,如果type==Area.class我们可以安全地t转换为Area和(从返回的值areaService.createAreaAreaT。因此,强制转换是安全的(即使是未知类型的强制转换T)。

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

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

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

于 2016-07-27T19:18:13.773 回答
1

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

接着

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

身份

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

在您的示例中不起作用的是,areaService::createArea并且countryService::createCountry适用Functions于具体类型。

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

于 2016-07-26T20:48:45.397 回答