我的意思是,而不是自己写这个:
public interface Func<TInput, TResult>
{
TResult call(TInput target) throws Exception;
}
public interface Action<T>
{
void call(T target) throws Exception;
}
答案 0 :(得分:79)
在Java 8中,等价物分别是java.util.function.Function<T, R>
和java.util.function.Consumer<T>
接口。同样,java.util.function.Predicate<T>
相当于System.Predicate<T>
。正如其他地方所提到的,这些是接口而不是委托。
相关的一点:我目前正在严重依赖以下实用程序类来做类似LINQ的扩展方法:
abstract class IterableUtil {
public static <T> Iterable<T> where(Iterable<T> items, Predicate<T> predicate) {
ArrayList<T> result = new ArrayList<T>();
for (T item : items) {
if (predicate.test(item)) {
result.add(item);
}
}
return result;
}
public static <T, R> Iterable<R> select(Iterable<T> items, Function<T, R> func) {
ArrayList<R> result = new ArrayList<R>();
for (T item : items) {
result.add(func.apply(item));
}
return result;
}
}
与System.Linq.Enumerable.Where<TSource>
和System.Linq.Enumerable.Select<TSource, TResult>
不同,我在这里介绍的LINQ类方法并不是懒惰的,并且在将结果集合返回给调用者之前完全遍历源集合。尽管如此,我发现它们仅仅用于纯粹的语法目的,并且如果必要可能会变得懒惰。给定
class Widget {
public String name() { /* ... */ }
}
可以做到以下几点:
List<Widget> widgets = /* ... */;
Iterable<Widget> filteredWidgets = IterableUtil.where(widgets, w -> w.name().startsWith("some-prefix"));
我更喜欢以下内容:
List<Widget> widgets = /* ... */;
List<Widget> filteredWidgets = new ArrayList<Widget>();
for (Widget w : widgets) {
if (w.name().startsWith("some-prefix")) {
filteredWidgets.add(w);
}
}
答案 1 :(得分:32)
Callable界面类似于Func。
Runnable接口类似于Action。
通常,Java使用匿名内部类作为C#委托的替代。 例如,这是您添加代码以响应GUI中按钮按下的方式:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
...//code that reacts to the action...
}
});
答案 2 :(得分:5)
重载的Func委托(除了委托与匿名类问题之外)的优雅在于它们支持0到16个参数(Func<TResult>
,Func<T, TResult>
,Func<T1, T2, TResult>
等。)
不幸的是,由于类型擦除,这在Java中是不可能的。仅通用类型参数的类不能有所不同。
Java 8现在为BiConsumer
带来了一个名为Action<T, T2>
的动物园,因为Java不允许原始类型参数,BiIntConsumer
。但是,“动物园”并不是很大,而且我不知道有一个扩展它的图书馆。对于像(int, int) => void
这样的函数类型文字有一个很棒的建议,但它没有被采用。
答案 3 :(得分:3)
真的没有相应的东西。您可以在Java中创建匿名内部类,但往往存在特定的接口,而不是像Func和Action这样的通用接口。
答案 4 :(得分:3)
Java没有委托的概念。有关变通方法,请参阅A Java Programmer Looks at C# Delegates:
虽然C#具有一组功能 类似于Java,它增加了几个 新的和有趣的功能。 代表团是对待一个人的能力 方法作为第一类对象。一个C# delegate用于Java开发人员 将使用单个接口 方法。在本文中,使用 讨论了C#中的代表和代码 是为Java代表提供的 可以执行类似的对象 功能。下载源代码 这里。
答案 5 :(得分:2)
对于Func<T>
使用:java.util.function.Supplier
http://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html
答案 6 :(得分:2)
您可以像这样使用java.util.Function
PHP: v7.3
Laravel: v5.8.4
MariaDB: v10.3.13
Homestead: v8.1.0
但是,如果要与多个参数一起使用它(如C#Func那样),则必须按照以下方式定义FunctionalInterface版本
Function<Employee, String> f0 = (e) -> e.toString();
然后您可以将变量与参数个数一起使用
@FunctionalInterface
public interface Func2Args<T, T1, R> {
R apply(T t, T1 t1);
}
@FunctionalInterface
public interface Func3Args<T,T1,T2,R> {
R apply(T t, T1 t1, T2 t2);
}
答案 7 :(得分:1)
对于Java 8之前的版本
对于C#中的方法回调,我这样使用:
public void MyMethod(string par1, string par2, Action<int> callback, Action<int, string> callback2)
{
//Async Code
callback.invoke(1);
callback2.invoke(4, "str");
}
并调用它:
utils.MyMethod("par1", "par2", (i) =>
{
//cb result
}, (i, str) =>
{
//cb2 result
});
我用Java制作了小的抽象类
package com.example.app.callbacks;
public abstract class Callback1<T> {
public void invoke(T obj) {}
}
package com.example.app.callbacks;
public abstract class Callback2<T, T2> {
public void invoke(T obj, T2 obj2) {}
}
package com.example.app.callbacks;
public abstract class Callback3<T, T2, T3> {
public void invoke(T obj, T2 obj2, T3 obj3) {}
}
...ETC
Java方法如下:
public void myMethod(String par1, String par2, final Callback1<int> callback, final Callback2<int, String> callback2) {
//Async Code
callback.invoke(1);
callback2.invoke(4, "str");
}
现在在用Java调用时:
utils.myMethod("par1", "par2", new Callback<int>() {
@Override
public void invoke(int obj) {
super.invoke(obj);
//cb result
}
}, new Callback2<int, String>() {
@Override
public void invoke(int obj, String obj2) {
super.invoke(obj, obj2);
//cb2 result
}
});
这也可以通过将回调函数传递/设置到要在其中调用它们的类来实现,同样的方法也可以用于创建接口:
package com.example.app.interfaces;
public interface MyInterface<T> {
void makeDo(T obj);
void makeAnotherDo();
}
答案 8 :(得分:1)
从 Java 8 开始,Func 和 Action 可以通过函数式接口和 Lambda 表达式来实现。
函数式接口是一种只有一个抽象方法的接口。
@FunctionalInterface
interface Drawable {
void Draw();
}
@FunctionalInterface
属性是可选的。同时,Lambda 表达式的概念对于 C# 和 Java 来说是相同的。
下面的 Java 和 C# 代码是等价的:
class App
{
public static void Main(string[] args)
{
Action action = () => { Console.WriteLine("Printing from App class"); };
action();
}
}
@FunctionalInterface
interface Drawable {
void Draw();
}
public class App {
public static void main(String[] args) throws Exception {
Drawable drawable = ()->System.out.println("Printing from App class");
drawable.Draw();
}
}
在 Java 中,Func 和 Action 被函数式接口取代。
有了这种接口,Java 就不需要特别有 Func 和 Action 委托类型,因为我们可以创建任何满足 Func 和 Action 的接口(即它的参数和返回类型)。因此,Java 中的代码比 C# 版本要冗长一些。
(这是从https://www.byteinthesky.com/tutorials/func-and-action-equivalent-in-java/总结的)
答案 9 :(得分:0)
如果您有 C# 背景(就像我一样)并且正在寻找:
public delegate TResult Func<in T1,in T2,out TResult>(T1 arg1, T2 arg2);
看看:
public interface BiFunction<T, U, R>
答案 10 :(得分:0)
这是我的实现,缺少 Action
package x.y.delegate;
public class IAction {
public interface _0 { void execute(); }
public interface _1<T> { void execute(T p); }
public interface _2<T1, T2> { void execute(T1 p1, T2 p2); }
public interface _3<T1, T2, T3> { void execute(T1 p1, T2 p2, T3 p3); }
public interface _4<T1, T2, T3, T4> { void execute(T1 p1, T2 p2, T3 p3, T4 p4); }
public interface _5<T1, T2, T3, T4, T5> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5); }
public interface _6<T1, T2, T3, T4, T5, T6> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6); }
public interface _7<T1, T2, T3, T4, T5, T6, T7> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7); }
public interface _8<T1, T2, T3, T4, T5, T6, T7, T8> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8); }
public interface _9<T1, T2, T3, T4, T5, T6, T7, T8, T9> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9); }
public interface _10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10); }
public interface _11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11); }
public interface _12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12); }
public interface _13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13); }
public interface _14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14); }
public interface _15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15); }
public interface _16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> { void execute(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15, T16 p16); }
}
class DoSomething {
public void doSm(IAction._1 ack, IAction._2 ack2) {
}
}
或者您可以在此链接中找到我的库,其中包括 Action、Func、Predicate 和 Tuple 的定义: https://github.com/ThinhVu/javaext 或https://jitpack.io/#ThinhVu/javaext/1.0.0