首页 > 代码库 > Java实现泛型委托类似C#Action<T>
Java实现泛型委托类似C#Action<T>
一、C# Action<T> 泛型委托(帮助理解委托)
描述:
封装一个方法,该方法只采用一个参数并且不返回值.
语法:
public delegate void Action<T>(T arg);
T:
参数类型:此委托封装的方法的参数类型
arg:
参数:此委托封装的方法的参数
备注:
通过此委托,可以将方法当做参数进行传递.Action<T> 泛型委托:封装一个方法,该方法只采用一个参数并且不返回值。可以使用此委托以参数形式传递方法,而不用显式声明自定义的委托。该方法必须与此委托定义的方法签名相对应。也就是说,封装的方法必须具有一个通过值传递给它的参数,并且不能返回值。当然泛型委托不只是只能支持一个参数,它最多可以支持四个参数。
例子:
在使用 Action<T> 委托时,不必显式定义一个封装只有一个参数的方法的委托。以下代码显式声明了一个名为 DisplayMessage 的委托,并将对 WriteLine 方法或 ShowWindowsMessage 方法的引用分配给其委托实例。
using System; using System.Windows.Forms; delegate void DisplayMessage(string message); public class TestCustomDelegate { public static void Main() { DisplayMessage messageTarget; if (Environment.GetCommandLineArgs().Length > 1) messageTarget = ShowWindowsMessage; else messageTarget = Console.WriteLine; messageTarget("Hello, World!"); } private static void ShowWindowsMessage(string message) { MessageBox.Show(message); } }
以下简化了此代码,它所用的方法是实例化 Action<T> 委托,而不是显式定义一个新委托并将命名方法分配给该委托。
using System; using System.Windows.Forms; public class TestAction1 { public static void Main() { Action<string> messageTarget; if (Environment.GetCommandLineArgs().Length > 1) messageTarget = ShowWindowsMessage; else messageTarget = Console.WriteLine; messageTarget("Hello, World!"); } private static void ShowWindowsMessage(string message) { MessageBox.Show(message); } }
下面使用 Action<T> 委托来打印 List<T> 对象的内容。 使用 Print 方法将列表的内容显示到控制台上。 此外还使用匿名方法将内容显示到控制台上。 请注意该示例不显式声明 Action<T> 变量。 相反,它传递方法的引用,该方法采用单个参数而且不将值返回至 List<T>.ForEach 方法,其单个参数是一个 Action<T> 委托。 同样,在 C# 示例 中,Action<T> 委托不被显式地实例化,因为匿名方法的签名匹配 List<T>.ForEach 方法所期望的 Action<T> 委托的签名。
using System; using System.Collections.Generic; class Program { static void Main() { List<String> names = new List<String>(); names.Add("Bruce"); names.Add("Alfred"); names.Add("Tim"); names.Add("Richard"); // Display the contents of the list using the Print method. names.ForEach(Print); // The following demonstrates the anonymous method feature of C# // to display the contents of the list to the console. names.ForEach(delegate(String name) { Console.WriteLine(name); }); } private static void Print(string s) { Console.WriteLine(s); } }
二、总结:
定义:委托就是可以自定义方法的执行时间。
要点:
1. 定义方法。
2. 声明对象。
3. 给对象赋值(也就是执行方法)。
三、Java 实现委托
Java是不可能实现委托的, 因为压根就没有这个机制, Java中要实现委托的类似功能只能用接口/内部类, 随便看一个AWT / Swing的程序就知了 。
1. 内部类实现委托
<span style="color:#000000;">public class 实现委托{ public static void main(String[] args){ //声明对象 实现委托 test = new 实现委托(); 委托 t =test. new 委托(); //对象赋值 执行方法 t.T(); } //定义委托 class 委托{ public void T(){ System.out.println("测试委托"); } } }</span>
2. 接口实现委托
<span style="color:#000000;">public interface 委托 { public void T(); } public class 实现委托 implements 委托{ public static void main(String[] args){ 实现委托 test = new 实现委托(); test.T(); } public void T(){ System.out.println("测试委托"); } }</span>
四、泛型委托在项目中的应用
1. C#泛型委托在项目中的应用参考网址:http://www.cnblogs.com/ASPNET2008/archive/2010/04/05/1704405.html
2. C#项目实例
问题:我想大家在做异常时,都会利用try catch来捕获异常,日志就在catch块中完成,但每个方法都写一堆的try catch往往显的有点别扭。虽然写程序时提倡尽量去捕获具体的错误异常,但总会有你预想不到的异常抛出,为此直接捕获Exception算是不错的做法。
具体场景:在客户端调用WCF服务时,我们都需要在客户做异常处理,最常见的错误异常为CommunicationException,TimeoutException,Exception示例如下:
try { //执行方法调用 ...... (proxy as ICommunicationObject).Close(); } catch (CommunicationException ex) { (proxy as ICommunicationObject).Abort(); WebLog.SquareLog.CommonLogger.Error("取积分广场首页酒店数据异常CommunicationException:" + ex.ToString()); } catch (TimeoutException ex) { (proxy as ICommunicationObject).Abort(); WebLog.SquareLog.CommonLogger.Error("取积分广场首页酒店数据超时TimeoutException:" + ex.ToString()); } catch (Exception ex) { (proxy as ICommunicationObject).Close(); WebLog.SquareLog.CommonLogger.Error("取积分广场首页酒店数据异常Exception:" + ex.ToString()); }
但如果这种代码遍布整个项目,我想就有重构的必要了,因为项目中最好不要出现类似复制的代码出现,为此我们可以采用Invoke形式来重构我们已有代码,下面给出两个方法,一个是没有返回值的,一个是有值的。
使用Action<T>后代码如下:
public static void Invoke<TContract>(TContract proxy, Action<TContract> action) { try { action(proxy); (proxy as ICommunicationObject).Close(); } catch (CommunicationException ex) { (proxy as ICommunicationObject).Abort(); WebLog.SquareLog.CommonLogger.Error("取积分广场首页酒店数据异常CommunicationException:" + ex.ToString()); } catch (TimeoutException ex) { (proxy as ICommunicationObject).Abort(); WebLog.SquareLog.CommonLogger.Error("取积分广场首页酒店数据超时TimeoutException:" + ex.ToString()); } catch (Exception ex) { (proxy as ICommunicationObject).Close(); WebLog.SquareLog.CommonLogger.Error("取积分广场首页酒店数据异常Exception:" + ex.ToString()); } } public static TReturn Invoke<TContract, TReturn>(TContract proxy, Func<TContract, TReturn> func) { TReturn returnValue = http://www.mamicode.com/default(TReturn);>
如何调用:可以看出客户端代码已经变成一条简洁代码了,它即完成了完整的异常处理,而且也把所有能够捕获的异常信息记录下来。
调用代码:
list = ErrorHandler.Invoke<ISearchHotelForSquare, List<HotelGenericInfo>>(cli, proxy => proxy.GetHotelGenericListForSquare(requestInfo).ToList());3. 总结
自己理解:委托用在当很多代码大部分代码相同,部分代码不同且不同的代码在整体代码中的位置相同的时候,可以将整体的部分封装成一个方法(方法名如:all),然后将不同的部分的代码写成一个没有返回值的方法(方法名如:part),然后使用Action<T>,将part方法像参数一样传递给all函数。这样实现代码的重构。
上面是在C#中用Action<T>实现的。
Java中没有Action<T>,还不能实现泛型委托,只能使用接口和内部类来实现。
下面是Java实现和Action<T>一样功能的例子.
例子如下:
(1)公用方法
public class AllClass { public static void all(String s,Common common){ //此处可以写公用的代码 common.print(s); //此处可以写公用的代码 } }
(2)不同代码要实现的接口
public interface Common { public void print(String s); }
(3)实现接口的第一个类
public class A implements Common{ public void print(String s){ System.out.print(s+="A"); } public static void main(String[] args) { String s = "test"; AllClass.all(s,new A()); } }
(4)实现接口的第二个类
public class A implements Common{ public void print(String s){ System.out.print(s+="A"); } public static void main(String[] args) { String s = "test"; AllClass.all(s,new A()); } }
Java实现泛型委托类似C#Action<T>