Java 功能和消费者限制
我决定在我的方法中使用函数作为参数,并发现了一些不愉快的事情。以下是一个例子:Java 功能和消费者限制,java,lambda,java-8,Java,Lambda,Java 8,我决定在我的方法中使用函数作为参数,并发现了一些不愉快的事情。以下是一个例子: final Random random = new Random(); public interface Animal { public void sleep(); } public class Cat implements Animal { public boolean isAffectionate() { return random.nextBoolean(); }
final Random random = new Random();
public interface Animal {
public void sleep();
}
public class Cat implements Animal {
public boolean isAffectionate() {
return random.nextBoolean();
}
public void meow() {
System.out.println("meow");
}
@Override
public void sleep() {
System.out.println("my sofa");
}
}
public class Dog implements Animal {
public boolean isAngry() {
return random.nextBoolean();
}
public void bark() {
System.out.println("woof-woof");
}
@Override
public void sleep() {
System.out.println("my carpet");
}
}
public boolean isOwnerAtHome() {
return random.nextBoolean();
}
public <T, A extends Animal> T anyAction(Class<A> clazz, Function<A, T> action)
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
A animal;
animal = (A) clazz.getConstructors()[0].newInstance();
T t;
if (isOwnerAtHome()) {
t = action.apply(animal);
} else {
animal.sleep();
t = action.apply(animal);
}
return t;
}
要查看void
活动,我必须使用以下方法:
public <A extends Animal> void voidAction(Class<A> clazz, Consumer<A> action)
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Function<A, Boolean> function = animal -> {
action.accept(animal);
return true;
};
anyAction(clazz, function);
}
很乱。即使是方法(anyAction
和voidAction
)也应该有不同的名称
使用lambdas和不完全重写是否可以减少混乱?通常我们使用一些语义来区分返回结果的函数和不返回结果的函数,例如:
static void <A extends Animal> void action(
Class<A> type,
Consumer<? super A> theAction) {...}
static void <A extends Animal, T> query(
Class<A> type,
Function<? super A, ? extends T> theQuery) {...}
Animal.action(Cat.class, Cat::meow);
boolean result =
Animal.query(Cat.class, Cat::isAffectionate);
或可能考虑用不同的方式来解释:
private static <A extends Animal> Optional<A> create(
Class<A> type) throws NoSuchMethodException, InstantiationException, IllegalAccessException {
A a = type.getConstructor().newInstance();
if (!a.isOwnerHome()) {
a.sleep();
}
return a;
}
// "action"
theAction.accept(create(type));
// "query"
return theQuery.apply(create(type));
私有静态可选创建(
类类型)抛出NoSuchMethodException、InstanceionException、IllegalAccessException{
A=type.getConstructor().newInstance();
如果(!a.isOwnerHome()){
a、 睡眠();
}
返回a;
}
//“行动”
接受(创建(类型));
//“查询”
返回query.apply(创建(类型));
一般来说,请记住,API的内部可能并不漂亮或完美,而目标是从外部使用它
假设lambda的设计方式是消费者
以某种方式隐式转换为函数
。这对于希望重用一点代码的API设计人员来说是很方便的,但这将为这些API的用户以无意义/不正确的方式使用它们打开一条通道:
<T> void send(List<T> elements) {
elements.stream()
// using 'map' to log
// when 'peek' is designed for this purpose
.map(e -> Debug.log("sending " + e))
.forEach(this::send);
}
void发送(列表元素){
元素流()
//使用“映射”进行日志记录
//当“peek”设计用于此目的时
.map(e->Debug.log(“发送”+e))
.forEach(this::send);
}
也许你认为它很复杂,因为你让它变得复杂:
public <T, A extends Animal> T anyAction(Supplier<A> s, Function<A, T> action) {
A animal=s.get();
if (!isOwnerAtHome()) animal.sleep();
return action.apply(animal);
}
public <A extends Animal> void anyAction(Supplier<A> s, Consumer<A> action) {
anyAction(s, a -> { action.accept(a); return null; });
}
public boolean booleanCatActionToday() {
return anyAction(Cat::new, Cat::isAffectionate);
}
public void voidCatActionToday() {
anyAction(Cat::new, Cat::meow);
}
您可以静态导入
,并且您永远不需要重载方法,因为您可以调用接受函数的方法
public void voidCatActionToday() {
anyAction(Cat::new, noResult(Cat::meow));
}
<T> void send(List<T> elements) {
elements.stream()
// using 'map' to log
// when 'peek' is designed for this purpose
.map(e -> Debug.log("sending " + e))
.forEach(this::send);
}
public <T, A extends Animal> T anyAction(Supplier<A> s, Function<A, T> action) {
A animal=s.get();
if (!isOwnerAtHome()) animal.sleep();
return action.apply(animal);
}
public <A extends Animal> void anyAction(Supplier<A> s, Consumer<A> action) {
anyAction(s, a -> { action.accept(a); return null; });
}
public boolean booleanCatActionToday() {
return anyAction(Cat::new, Cat::isAffectionate);
}
public void voidCatActionToday() {
anyAction(Cat::new, Cat::meow);
}
public static <T> Function<T,Void> noResult(Consumer<T> c) {
return t -> { c.accept(t); return null; };
}
public void voidCatActionToday() {
anyAction(Cat::new, noResult(Cat::meow));
}