【原创】转载请注明出处,谢谢合作!

Java的泛型对于帮助我们构建自己的工具包,实在是一个利器,接下来我们一起讨论如何构建一些简单易用的工具,欢迎评论:

一、打印函数工具包

一般我们使用系统的打印函数如下:

1 System.out.println();

这条语句的作用是在控制台进行输出,简单的输出直接利用它貌似就可以了,但是这种方式有一些缺陷:

  1)我们通常使用一些IDE进行开发java程序,系统打印函数一般直接输出到控制台上,假设这些打印的信息对于帮助查找bug是有利用价值的,那么发布程序后,如果出现错误我们肯定希望能够在日志中查找出错的地方,怎么做呢,一般有两种方案,第一是直接将System.out设为文件流的PrintStream,如:

PrintStream out = null;try {out = new PrintStream("D:/log_"+(new Date()).getTime()+".txt");} catch (FileNotFoundException e) {// TODO Auto-generated catch block
            e.printStackTrace();}
System.setOut(out);

  这样,凡是System.out输出的信息都写入到文件中,这种方式貌似很酷,不过当你想要重新回到控制台输出时,就得重新将System.out设回来;第二种方案是使用一些第三方强大的日志工具,最流行的当然要数log4j,你可以更灵活的记录日志,不过你仍旧得按log4j的调用方法来记录信息。

  2)System.out太长了,输出很不便,特别是需要分行输出很多内容的时候,不仅要写一堆的System.out.print,还要用很多的+把要输出的信息连起来。

所以,让我们来包装一下,让系统可以更灵活地记录信息。

第一段代码是简单地封装一下print和println,代码如下:

  public class P{  public static <T> void p(T o){System.out.print(o);}public static <T> void pl(T o){System.out.println(o);}public static void pl(){System.out.println();}}

  一定要使用泛型吗?其实在这里不一定,因为这里的o实际上就是Object,但是这不影响我们使用泛型,我只是想说明,这个函数具有“可以传入任意类型的对象”这一概念。现在我们可以更灵活地使用日志记录了,因为所有的入口都在P这个类里,你可以在这里将要输出的内容放置到任意的终端,控制台、文件,随便,只要改了这里的三个基本实现就行。

  第一段代码只是减少了我们敲写那么长的System.out.println函数,但并没有提供其他额外的方便,现在我们需要输出更加丰富的信息,例如,输出一个数组,Map、一个List,甚至按位打印一个Byte,作为示例,我们看看如下的代码(第二段代码):

    public static <K,V> void pm(Map<K,V> map){pl("-----------------------------------------------------");for(K k:map.keySet()){pl(k+"\t"+map.get(k)+";");}pl("-----------------------------------------------------");}public static <T> void pa(T[] array){pl("-----------------------------------------------------");for(T t:array){pl(t);}pl("-----------------------------------------------------");}public static void pb(Byte b){for(int i=7;i>=0;i--){if(((b&(1<<i))!=0x00 ))p('1');else p('0');}pl();}public static void pb(Byte[] bs){int cnt = 0;for(byte b:bs){p((char)b+":");for(int i=7;i>=0;i--){if(((b&(1<<i))!=0x00 ))p('1');else p('0');}p(" ");if(++cnt%4==0)pl();}pl();}

  现在我已经能够很方便地使用P.pm、P.pa或者P.pb方便地输出map,array,byte等信息了,它们利用了我们前面提供的基本函数。你还可以添加更丰富的格式化输出函数,这取决于你的创造力。

  第二段代码给我们的工作减轻了很多负担,以后你想要输出一个map的内容,就不用自己写for循环了,你想查看一个byte里的位数信息,也不用自己去做转化了,(当然你可以选择Integer.toBinaryString函数,不过这个函数并没有按美观的方式格式化,而且它删除了二进制串前面的0,有时候这并不是我们预想的)。

  现在我们还有一个新的需求,我们要输出一系列的变量,把他们打印成一行,并且使用变量之间用指定间隔符间隔开,如果你看到这个需求,初始下你会选择两种解决方案,第一种使用+号,这太麻烦了,考虑如下代码:

    String name = ”Snuby";String code1 = "Java";String code2 = "JavaScript";P.pl(name+" "+"like"+" "+code1+" "+"and"+" "+code2);

  这里基于假设,将间隔符单独列出来,这样看起来就更清晰了,反映出的问题也更明显,用了太多的“+”号,调用太复杂了,能够更简洁一点吗?

  你的第二种方案是使用System.out.printf函数,考虑如下代码:

String name = ”Snuby";
String code1 = "Java";
String code2 = "JavaScript";

System.out.printf("%s like %s and %s\n",name,code1,code2);

  貌似简单多了,你完全可以再写一个P.pl多态函数来匹配这种方式,但是当间隔符不是空格的时候,你发现还是很忧伤,例如间隔符需要"\t"的时候,你需要输入n此的"\t",多麻烦啊,让工具包帮我们做吧!

    public enum INTEVEL{COMMA(";"),COLON(":"),MINUS("-"),POINT("."),SPACE(" "),TAB("\t");private String value;INTEVEL(String value){this.value = value;}@Overridepublic String toString(){return this.value;}}public static <T> void pl(T... objects){INTEVEL intevel = INTEVEL.SPACE;if(objects.length>0&&objects[objects.length-1] instanceof INTEVEL){intevel = (INTEVEL) objects[objects.length-1];for(int i =0;i<objects.length-1;i++){p(objects[i]+intevel.toString());}pl();return;}for(Object obj:objects){p(obj+intevel.toString());}pl();}

  看这段代码,我们新加入了一个枚举类型,它的作用是枚举一些常见的间隔符,你可以根据需要往里添加,该枚举值会对应它们所代表的的间隔符,可以通过toString返回。接着我们又使用了泛型,这里泛型仍然只是表示“任意类型的数据”这一概念,你可以考虑将它换成Object,这没有影响。

  我们的新函数测试正常,而且使用起来很方便,它默认使用space即空格作为间隔符,调用代码如下:

String name = "Snuby";
String code1 = "Java";
String code2 = "JavaScript";
P.pl(name,"like",code1,"and",code2);

  如果你要更换间隔符,只要在最后一个参数上添加间隔符类型,就会将默认值给替换掉了,使用方式如下:

String name = "Snuby";
String code1 = "Java";
String code2 = "JavaScript";
P.pl(name,"like",code1,"and",code2,P.INTEVEL.TAB);

  现在,是不是舒服很多了呢?你可以根据你的需要往P里面添加函数,这取决于你的审美观以及你的偷懒精神,这是个伟大的精神!

  第一部分再贴一点小技巧,看到上面的调用实例没,每次调用都要在前面加个“P.”,嫌麻烦吗,那么在你的类头里加入类似的这条语句吧:

import static com.snuby.P.*;

  现在,你连“P.”都省了,-_-,懒惰使人类进步!

转载于:https://www.cnblogs.com/snuby/p/3161064.html

Java,使用泛型构建自己的工具包——包装System.out相关推荐

  1. java使用泛型后消除泛型_如何以及何时使用泛型

    java使用泛型后消除泛型 本文是我们名为" 高级Java "的学院课程的一部分. 本课程旨在帮助您最有效地使用Java. 它讨论了高级主题,包括对象创建,并发,序列化,反射等. ...

  2. java实现泛型检索_高级Java泛型:检索泛型类型参数

    java实现泛型检索 在JDK5中引入Java泛型之后, Java泛型Swift成为许多Java程序的组成部分. 但是,乍一看似乎很简单的Java泛型,程序员很快就会迷失此功能. 大多数Java程序员 ...

  3. java之泛型_java之泛型

    什么是泛型? 泛型是JDK1.5新加入的,解决数据类型的安全性问题,其主要原理是在类声明时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型.这样在类声明或实例化时只要指定好需要的具体 ...

  4. Java通过泛型的模板类型实例化对象

    Java通过泛型的模板类型实例化对象 最近自己研究了下mvvm框架,使用泛型的方式可节省很多代码,并且可以合并很多冗余代码,为了最大化的精简代码想到了通过泛型的type用反射的方式实例化对象,这样对象 ...

  5. Java中泛型的各种使用

    Java中的泛型的使用: 1.普通的泛型使用在使用类的时候后面的<>中的类型就是我们确定的类型.public class MyClass1<T> {//此处定义的泛型是Tpri ...

  6. 【Java】泛型中 extends 和 super 的区别?

    <? extends T>和<? super T>是Java泛型中的"通配符(Wildcards)"和"边界(Bounds)"的概念. ...

  7. 聊聊Java的泛型及实现

    泛型基础 泛型是对Java语言类型系统的一种扩展,有点类似于C++的模板,可以把类型参数看作是使用参数化类型时指定的类型的一个占位符.引入泛型,是对Java语言一个较大的功能增强,带来了很多的好处: ...

  8. java 8中构建无限的stream

    文章目录 简介 基本使用 自定义类型 总结 java 8中构建无限的stream 简介 在java中,我们可以将特定的集合转换成为stream,那么在有些情况下,比如测试环境中,我们需要构造一定数量元 ...

  9. java添加容器_如何为Java应用程序构建docker容器

    我想要做的是为我的Java应用程序构建一个docker镜像,但对于大多数编译语言,以下注意事项应该是正确的. 问题 在我的构建服务器上,我想为我的应用程序生成一个docker镜像作为可交付成果.为此, ...

最新文章

  1. LeetCode简单题之字符串中的最大奇数
  2. python从入门到精通怎么样-Python 从入门到精通:一个月就够了
  3. Deep learn toolbox:CNN BP求导解析
  4. 魏伟:学习音视频技术要先理论再实现
  5. Python循环定时服务功能(相似contrab)
  6. python字典定义方式_Python字典常用方法及汇总
  7. Lucene创建索引入门案例
  8. nyoj744 蚂蚁的难题(-)
  9. C语言(CED)编写一个程序,求两个字符之间的加减运算。
  10. 千里眼摄像头支持对象存储吗_3.5ms超高速写入、支持125℃工作的EEPROM“BR24H-5AC系列”...
  11. C# 判断上传图片是否被PS修改过的方法
  12. 阿里免费开放一切AI算力的背后是什么?
  13. 10 Python - Python列表list
  14. Spring中引用不同xml中的bean
  15. 【iOS】使用 otool 命令查看 App 所使用的动态库
  16. c语言中isupper用法,C 库函数 - isupper()
  17. videojs播放器插件使用详解
  18. svn: E230001: Server SSL certificate verification failed: certificate issued for a different hostnam
  19. 你可能没听过的11个Python库
  20. matlab snr mse,MATLAB 均方根误差MSE、两图像的信噪比SNR、峰值信噪比PSNR、结构相似性SSIM...

热门文章

  1. mysql限制登录次数_mysql会话控制限制登录次数(connection_control插件)
  2. 【kafka】kafka 消费报错 Failed to add leader for partitions
  3. 【Clickhouse】Clickhouse 外部存储引擎之 hdfs
  4. 10-30-010-安全简介-Kafka 安全机制
  5. 【Maven】Maven slf4j-api 出现 NoClassDefFoundError:org/slf4j/event/LoggingEvent
  6. 【Flink】flink-connector-elasticsearch5与flink-connector-elasticsearch6 有什么区别
  7. java.lang.Runtime.availableProcessors返回可用处理器的Java虚拟机的数量
  8. mysql bdb 锁_BDB锁共享区域
  9. API接口应该如何设计?
  10. Flask实现分页功能