进入 Java8 之后我们会发现接口可以有方法实现了,这与我们一直看待 Java 接口的观念产生了冲突,不过也别急,接口中的方法实现必须是一个默认方法,即像
本文旨在探讨 Java8 的默认接口方法存在的合理性,Java8 在这点上如何保持与前面版本的兼容性。1interface Shape { 2 default boolean isShape() { 3 return true; 4 } 5}
Lambda 和方法引用使得 Java 语言更具表现力。说到 Lambda 和方法引用的关系,Lambda 表达式的目的就是让你更为便捷的去绕过对象直接引用方法。
接口应该是相对稳固的,我们应该有这样的经验,类中使用了接口中定义的常量,如果在接口中改变了该常量值,单纯的替换接口对应的 class 文件是不奏效的,因为编译类时其实是把接口中的常量直接固化在类中了。如果类中要体现出最新常量值,那么使用接口的类也要重新编译。即使在接口中添加或改变了方法定义,也不能强制使用到它的类重新编译,早先的类完全可以自由的运行,因为接口中定义的常量和方法的所有内容都在自身,类一旦编译后便可脱离所实现的接口而运转。 Read More- 用 Java 在控制台下输出用
System.out.print()这样的方法,那么要在同一行输出象 FTP 传文件那样的进度指示怎么做呢,它需要在同一行相同的位置上擦除并输出新百分数。比如前一行打印了 1%, 下一次就把 1% 擦除掉,同一位置上打印 2%,就形成了走进度的效果。如下:
我们要用到的办法是System.out.print("\b")就会在控制台下往回删掉一个字符,如果你想回删多个字符就打印多个 "\b" 吧,只回删除到当前行首,也就是不回影响到上一行的输出。怎么删除当前行全部输出或指定的字符数呢,两个办法:
输出足够多的 "\b",会删除到行首为止,这样做其实也不保险,谁知道上一行会多少字符呢
精确控制回删多少个字符,有时候也需要保留前面一些内容 Read More - 远离 Maven 工程有些时日了,也不知道当前还是否在流行 Maven 管理工程与依赖,当前类似工具有 Ant+Ivy, Grunt, sbt 和 Gradle。Web 工程的输出发布包没什么好说的,因为 <packaging>
war</packaging>,所以mvn package出来的 WAR 包里就有站点运行的所有内容了,用到的依赖会在 WEB-INF/lib 目录下列着。
而对于那些 <packaging>jar</packaging> 的工程,用mvn package只会生成一个 JAR 包,它所依赖的各个类库仍然分散在本地仓库中,而我们的发布包应该包含这些第三方依赖的。
假定,有一个 GoSSH Maven 工程,设定的版本是 0.0.1,它依赖了 jsch-0.1.50, commons-cli-1.3-SNAPSHOT,想要发布的包有如下布局GoSSH-0.0.1.jar
并且在 GoSSH-0.0.1.jar 中的 META-INF/MANIFEST.MF 文件中指定了 Read More
lib
jsch-0.1.50.jar
commons-cli-1.3-20140216.032825-101.jar #这里的 revision 号是随 SNAPSHOT 动态而定的 - 从 JMockit 系列的开篇 JMockit 之 Expectations 中了解到了一个最基本的 Mock 的写法,这里记录下在一个 Expectations 中如何同时 Mock 多个方法。基本框架是这样的:
1new Expectations(MyService.class, ExternalService.class) { 2 { 3 MyService.prefix("Unmi"); 4 result = "Welcome to website: "; 5 6 ExternalService.suffix("Unmi"); 7 result = "http://unmi.cc"; 8 } 9};
Java 语法告诉我们 new Expectations(){{......}} 省略号处的代码会在 Expectations 匿名类实例初始化时被调用,那么其中对 result 的赋值便是新创建的 Expectations 匿名类实例的 result 的属性值,那两次的 result 赋值难道不是以最后一个为准吗,有点文章了。先来跑个例子,见识一下现象,由三个类组成,分别是: Read More - 前面说过 JMockit 因身处前线,所以简直无不可,本节例子演示 JMockit 怎么 Mock 私有方法和私有属性,示例虽然是静态方法和属性,但因采用的是反射手法,所以这种 Deencapsulation 的 Mock 手段同样适用于公有的方法或属性,无论是否静态。
本文所用 JMockit 版本为 1.6, 可能网上所搜索的方法与此有所不同,请注意 JMockit 版本差异。仍需重复一下,运行 JMockit 的例子 classpath 上必须让 jmockit.jar 在 junit.jar 之前,或用 javaagent 参数来加载 jmockit.jar,并且 junit 要 4.8 及以上版本.
1. Mock 私有方法(非静态类似) Read More - TDD 推求测试先行,不光在自己代码未实现时可以先做好测试,即使平台依赖或第三方接口未准备好我们也能先行一步的,这就要对接口依赖进行 Mock。同时 Mock 也使得我们的测试代码在运行当中不至于随着第三方接口的沦陷而坠入深渊。
Java 中 Mock 工具也不少,像通用 EasyMock, jMock, Mockito, Unitils Mock, PowerMock, 再比如偏专业的 HttpMock, StrutsMock 等。但 JMock 与前面各位相比简直是全能选手,对 final/static/native/private 方法都能 Mock,功能上还远不止这些了,可以看看一个对比图 https://code.google.com/p/jmockit/wiki/MockingToolkitComparisonMatrix。
JMockit 是基于 Java5 的 java.lang.instrument 包开发的,所以它才能夺得先机,也可陷得更深。自然它要求 JDK5 及以上,JUnit 4.8 及以上版本。命令行下原来用 -javaagent:/.../lib/jmockit.jar 加载 JMockit,现在发现把 jmockit.jar 放在 classpath 下就 OK 的,但是必须放在 junit.jar 包之前,否则你会看到这个 java.lang.IllegalStateException: JMockit wasn't properly initialized; check that jmockit.jar precedes junit.jar in the classpath。 JMockit 有两种 Mock 方式:
1. Behavior-oriented(Expectations & Verifications) --- 基于代码执行行为的模仿,象黑盒测试
2. State-oriented(MockUp<GenericType>) --- 侵入类内部,随意模仿,似白盒,可以说是能为所欲为
此篇体验下第一种 Mock 方式,在测试代码中最直观就是那个new Expectations(...){{result = some;}},下面来看个实际的例子。应用场景是 Read More - 使用 Ant 进行自动化处理时,不想记住每一个 target 的名称,而是让默认的 target 列出需要的 target 出来,让用户输入名称或数字选择执行哪个 target。这样做自然是多了一步,有时候确也方便不少,但 Ant 还是有个缺点,它不能持久性的保持在 Ant 控制台下,持续的进行用户交互。
对于实现 Ant 的简单用户交互,我们可以借助于两个 Task,input 和 antcall, input 用来提示用户输入值,再根据 input 设定的属性来确定 antcall 调用哪个 target。执行完退出到系统 Shell 下,想要再来,就再执行一下 ant 吧,我也只能做到这一步了。
看下面的例子 build.xml 内容 Read More - 最早的时候,我们只需要 GET 和 POST 方法,POST 方法的引入也只是为了消除 URL 过长,参数隐藏,上传文件的问题,完全和语义无关。接触到 RESTful 之后,我们开始思考 GET 和 POST 的不同语义,并且十分必要的去发掘出所有的 HTTP method,HTTP/1.1 所实现的 method,见 RFC 2616, 有这些:
OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
规范是这么定义的,这还要看容器实现了多少,比如 Tomcat 7 中的 servlet api 实现了
doOptions, doGet, doHead, doPost, doPut, doDelete, doTrace 就差个 doConnect 了。
而我们这里要说的 PATCH method 是在 Servlet 3.0 和当前 Tomcat 7 中都提到的,也就是尚未实现它。
这也难怪,PATCH 在 2010 年三月份才成为正式的方法,见 RFC 5789。没有 PATCH 的时候我们进行更新的操作采用的是 PUT 方法。那么 PATCH 和 PUT 有什么区别呢?
同样可以从语义上去理解,有两方面的对比: Read More - JDK8 都快要出来了,在 JDK 5 中仍有许多好宝贝值得去挖掘。提到 JDK5 我们或许只知道它给了我们泛型,其实还有那个并发包 java.util.concurrent 却不那么引人注目,其实就是 NIO。
若是并发包是在某个 JDK 版本中单独奉上,反响就不同了,想想 JDK 6 似乎未带来多少改变--至少对于编程者来说没有明显感受。java.util.concurrent 包中的东西对于我们处理线程带来了很大的便利,例如线程池,线程同步,Future, Callable 等。
这里我记录一下 CountDownLatch 的使用,在此之前在处理
线程 A 等待线程 B,C,D 全部执行完后才继续执行 (比如要每个线程都访问一个 Web 服务,等所有的请求响应成功后进行结果处理)
这样场景的时候,我一般能想到的办法是,初始一个计数器,线程 B,C,D 各自初始化的时候,计数器加一,然后 A 线程等待,每个线程执行完后计数器减一,当计数器为 0 时表明所有任务执行完毕,就通知 A 可以开始运作起来。但这样的方案还是得小心的处理好同步的问题。 Read More - Lambda 允许我们定义匿名方法(即那个 Lambda 表达式,或叫闭包),作为一个功能性接口的实例。如果你不想把一个 Lambda 表达式写得过大,那么你可以把表达式的内容分离出来写在一个方法中,然后在放置 Lambda 表达式的位置上填上对那个方法的引用。
方法引用也应看作是一个 Lambda 表达式,所以它也需要一个明确的目标类型充当功能性接口的实例。简单说就是被引用的方法要与功能接口的 SAM(Single Abstract Method) 参数、返回类型相匹配。方法引用的引入避免了 Lambda 写复杂了可读性的问题,也使得逻辑更清晰。
为了应对方法引用这一概念, JDK8 又重新借用了 C++ 的那个 “::” 域操作符,全称为作用域解析操作符。
上面的表述也许不好明白,我看官方的那份 State of the Lambda 也觉得不怎么容易理解,特别是它举了那个例子很难让人望文生意。我用个自己写的例子来说明一下吧。
目前的 Eclipse-JDK8 版还不能支持方法引用的特性,幸好就是在昨天正式版的 NetBeans IDE 7.4 对 JDK8 有了较好的支持,所以在 NetBeans 7.4 中写测试代码。 Read More