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 中找到示例,例如
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
可以是任何东西,即 Integer
或 Stream
您可以在此处使用 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.class
是 Class<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 { }
并使 Area
和 Country
实现该接口。然后定义
public <T extends Region> Function<T,T> getCreateFunction(Class<T> type) {...}
并且只有为 class 实现(或扩展的接口)的实体传递 class 令牌才有效 Region
.
我正在学习 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 中找到示例,例如
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
可以是任何东西,即 Integer
或 Stream
您可以在此处使用 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.class
是 Class<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 { }
并使 Area
和 Country
实现该接口。然后定义
public <T extends Region> Function<T,T> getCreateFunction(Class<T> type) {...}
并且只有为 class 实现(或扩展的接口)的实体传递 class 令牌才有效 Region
.