- 浏览: 1989425 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (509)
- JavaEE (122)
- Oracle数据库 (29)
- JavaScript (37)
- SAP (5)
- MySql数据库 (7)
- JavaSE (4)
- Ajax (1)
- jQuery (13)
- SSH框架 (36)
- Web Service (10)
- JSF框架 (2)
- JBPM (0)
- ireport报表 (2)
- ibatis (5)
- Hibernate (31)
- JSP (11)
- Tomcat 服务器 (20)
- Other (19)
- JavaWeb (4)
- Maven (11)
- OSWorkFlow (10)
- HTML (13)
- Exception汇总 (7)
- SVN (2)
- 笑话 (1)
- JSTL (1)
- WebSphere Message Broker (13)
- ANT命令 (3)
- Liunx (12)
- Struts2 (26)
- Eclipse (6)
- DOS (3)
- Flex (11)
- WebSphere (1)
- 开发常用工具 (3)
- Junit (2)
- EJB (4)
- Struts1.2 (2)
- Jboss (1)
- Android (2)
- Java框架源码解析 (1)
- Spring (4)
- MyBatis (6)
- SpringMVC (4)
- Jetty (2)
- 数据库表设计 (1)
- SSO (4)
最新评论
-
贝塔ZQ:
也可以试试PageOffice插件,觉得更简单点
Jxl操作Excel设置背景、字体颜色、对齐方式、列的宽度 -
jia1208:
...
Could not publish server configuration for Tomcat v6.0 Server at localhost. -
u011274527:
赞
java.io.EOFException java.io.ObjectInputStream$PeekInputStream.readFully 错误 -
旭旭小牛啦:
怎么没哟了,继续赛
jQuery 选择器 -
wzw3919:
100行会报空指针
Java 解压缩zip文件
这里讲述的是一个非常让人尴尬的故事
我们有一个简单的java类:
- class Details {
- double getBalance();
- double getFixed();
- double getVariable();
- double getSpendDown();
- ...
- //各种getter以及其他相关的逻辑
- }
class Details { double getBalance(); double getFixed(); double getVariable(); double getSpendDown(); ... //各种getter以及其他相关的逻辑 }
现在业务逻辑需要对一些property做求和操作,求overallBalance, overallFixed之类的。
没什么了不起的,一个for循环分分钟搞定:
- static double getOverallBalance(Details[] arr){
- double sum = 0;
- for(int i=0; i<arr.length; i++) {
- sum += arr[i].getBalance();
- }
- }
static double getOverallBalance(Details[] arr){ double sum = 0; for(int i=0; i<arr.length; i++) { sum += arr[i].getBalance(); } }
同理,对overallFixed,代码大同小异,copy-paste先。
- static double getOverallFixed(Details[] arr){
- double sum = 0;
- for(int i=0; i<arr.length; i++) {
- sum += arr[i].getFixed();
- }
- }
static double getOverallFixed(Details[] arr){ double sum = 0; for(int i=0; i<arr.length; i++) { sum += arr[i].getFixed(); } }
这都没什么。可是当我写到第七个getOverallBlahBlah(arr)函数的时候,终于有点受不了了。这代码重复的虽然不多,但是架不住这么没完没了阿。
作为code-against-interface的推崇者,作为一个函数式编程的扇子,最自然的想法就是把不同的getter逻辑抽象成一个Getter接口,如下:
- interface Getter {
- double get(Details details);
- }
- static double sum(Details[] arr, Getter getter){
- double sum = 0;
- for(int i=0; i<arr.length; i++) {
- sum += getter.get(arr[i]);
- }
- }
interface Getter { double get(Details details); } static double sum(Details[] arr, Getter getter){ double sum = 0; for(int i=0; i<arr.length; i++) { sum += getter.get(arr[i]); } }
娜爱思啊。有比这代码更优雅的么?
然后各个求和的代码变成:
- double overallBalance = sum(details, new Getter(){
- public double get(Details details){
- return details.getBalance();
- }
- });
- double overallFixed = sum(details, new Getter(){
- public double get(Details details){
- return details.getFixed();
- }
- });
- ....
double overallBalance = sum(details, new Getter(){ public double get(Details details){ return details.getBalance(); } }); double overallFixed = sum(details, new Getter(){ public double get(Details details){ return details.getFixed(); } }); ....
嗯。几乎没有什么重复的逻辑了。
不过......
数数代码行数,怎么没有减少,反而略有盈余?仔细找找。发现原来的for loop是四行,现在的new Getter(){...}居然也是四行!!!
再加上一个sum()函数,我辛苦了半天的重构,居然代码行数增加了!
如果世界上有比一个java的匿名类的语法更臭的,那大概就是两个匿名类语法了。据说居然还有人质疑java 7引入closure语法的意义?
另一个方法是用apache commons beanutils的getProperty(),最终的语法会是:
double overallBalance = sum(details, "balance");
语法足够简单了,但是重构的时候就麻烦了,也没有code-completion可用。
尴尬阿。这么一个简单的for loop,用匿名类重构似乎不值得。但是就任由这七个(也许回头还会更多)长得一模一样的for loop这么站在这气我?
走投无路,开始琢磨奇技淫巧了。
先声明一个接口,来包含所有需要sum的property getter。
- private interface IDetails {
- double getBalance();
- double getFixed();
- double getVariable();
- double getSpendDown();
- ...
- //所有其它需要做sum的getter
- }
private interface IDetails { double getBalance(); double getFixed(); double getVariable(); double getSpendDown(); ... //所有其它需要做sum的getter }
然后让Details实现IDetails。Details的代码不用变。
class Details implements IDetails { ... //代码不变 }
戏肉来了。写一个dynamic proxy,来封装sum逻辑。
- static IDetails sumOf(final IDetails[] arr){
- return (IDetails)Proxy.newProxyInstance(
- getClass().getClassLoader(), new Class[]{IDetails.class}, new InvocationHandler(){
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- double sum = 0;
- for(int i=0; i<arr.length; i++) {
- sum += ((Double)method.invoke(arr[i], args)).doubleValue();
- }
- return new Double(sum);
- }
- });
- }
static IDetails sumOf(final IDetails[] arr){ return (IDetails)Proxy.newProxyInstance( getClass().getClassLoader(), new Class[]{IDetails.class}, new InvocationHandler(){ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { double sum = 0; for(int i=0; i<arr.length; i++) { sum += ((Double)method.invoke(arr[i], args)).doubleValue(); } return new Double(sum); } }); }
好了,接下来求sum的语法可以被简化为如下:
- double overallBalance = sumOf(arr).getBalance();
- double overallFixed = sumOf(arr).getFixed();
- ...
double overallBalance = sumOf(arr).getBalance(); double overallFixed = sumOf(arr).getFixed(); ...
而且,再需要sum新的property,只需要把这个getter放进IDetails接口,就大功告成了。
很有趣的dynamic proxy应用。不过,一个求和这么简单的事情居然要动用这种奇技淫巧,很值得自豪么?
要是在ruby里,我就直接:
sum(arr){balance}
该死的java啊!
发表评论
-
解决Java服务器端插入数据到Mysql中乱码问题--简单几步轻松解决乱码问题
2015-11-13 17:52 2414当写入数据到mysql数据库中发生乱码时.请检查以下几个地 ... -
设计模式之-代理模式-Proxy
2015-04-28 21:24 868使用代理模式之前需要知道代理模式能做什么? 能有哪些好处以及 ... -
构建高并发、服务化、低耦合企业级脚骨:springmvc+mybatis+restfull+webservice+bootstrap html5
2015-04-14 01:17 85SpringMVC + Mybatis + SpringS ... -
教您搭建大型互联网企业架构:springmvc+mybatis+restful+webservice+quartz+bootstrap
2015-04-13 21:54 99SpringMVC + Mybatis + SpringS ... -
大型互联网服务集成平台:springmvc+mybatis+restful+webservice+quartz+bootstrap html5
2015-04-13 21:49 81SpringMVC + Mybatis + SpringSe ... -
大型互联网服务集成平台:springmvc+mybatis+restfull+JMS+webservice+bootstrap
2015-04-12 23:36 22SpringMVC + Mybatis + SpringS ... -
大型互联网服务集成平台:springmvc+mybatis+restfull+JMS+webservice+bootstrap
2015-04-12 23:33 83SpringMVC + Mybatis + SpringS ... -
Maven构建大型互联网架构springmvc+mybatis+Restfull+Webservice+Bootstrap
2015-04-12 23:28 71SpringMVC + Mybatis + SpringS ... -
maven构建高大上开源架构:springmvc+mybatis+rest+bootstrap html5
2015-04-12 23:25 23SpringMVC + Mybatis + SpringS ... -
手机App后台架构:Springmvc+SpringSecurity+mybatis+Rest+Quartz+Bootstrap Html5( Maven构建)
2015-04-09 01:39 76APP后台架构Maven构建,模拟大型互联网架构,支持高并发 ... -
maven构建springmvc+mybatis+rest+webservice+bootstrap html5(cms开源项目)
2015-04-09 01:21 85SpringMVC + Mybatis + SpringS ... -
Java正则表达式
2014-11-26 21:03 1220Java正则表达式: package pack.ja ... -
Cannot convert value of type [org.springframework.cache.ehcache.EhCacheCache
2014-11-10 20:03 6247错误信息: [org.springframework.be ... -
Collections工具类中的frequency方法统计单词出现的次数
2013-11-05 21:30 2813最近发现了一个Collections中有一个很好用的方法: ... -
Java 压缩Excel文件生成.zip文件
2013-05-08 22:22 7950首先创建文件目录,然后生成Excel文件到创建的目录下, ... -
Java 解压缩zip文件
2013-05-08 13:14 8351不借助于其他的第三方 ... -
Jxl操作Excel设置背景、字体颜色、对齐方式、列的宽度
2013-04-06 22:26 57704最近项目中需要用到导出Excel文件,以下是我写了一个通过j ... -
java获取字节的长度.
2012-05-17 22:00 6744我们经常要获取中文,数字,或者英文字符所占字节的长度,下面就列 ... -
StringBuffer-reverse()字符反转功能
2012-05-17 21:42 7093在书上看到一个这样的例子, 采用最简便的方式把一串字符串反转过 ... -
java 打开IE
2012-05-23 22:14 1299Runtime.getRuntime().exec(" ...
相关推荐
在Java中,你可以通过定义方法来实现这个功能。例如,你可以创建一个名为`addNumbers(int num1, int num2)`的方法,该方法接受两个整数参数,并返回它们的和。这个方法的实现如下: ```java public int addNumbers...
这时,可以考虑使用`java.util.stream.Collectors.sumInt()`函数对流中的整数进行求和,这种方法可以有效地处理大量数据,避免一次性加载所有数据到内存。 总的来说,Java实现文件数据求和涉及文件读取、数据解析、...
- **数组操作函数**:Java的`Arrays`类提供了许多实用方法,如`sort()`排序数组,`equals()`比较数组内容,`copyOf()`复制数组等。 - **集合框架**:`ArrayList`和`LinkedList`等集合类可以动态增长,提供了更多的...
在 Java8 中,我们还可以使用 Stream 的其他方法来实现列表元素的属性求和操作,例如使用 collect 方法来将列表中的元素收集到一个新的集合中,然后使用 Stream 的 sum 方法来求和。 例如,我们可以使用以下代码来...
在这个压缩包文件中,我们可能找到一个或多个Java源代码文件,这些文件包含了对第67题的解答。描述中的“java_leetcode题解之第67题二进制求和”进一步确认了这个主题,意味着我们可能会看到如何用Java语言实现将两...
在这个案例中,我们将探讨如何使用`groupingBy`进行多字段分组以及如何实现分组求和。 首先,`groupingBy`的基本用法是根据一个单一的属性将集合元素分组。例如,给定一个包含水果名称的列表,我们可以很容易地按照...
首先,我们需要定义一个实体类 `GroupDetailDTO`,该类具有多个属性,包括 `headsetId`、`time`、`actConcreteTime` 和 `played`。然后,我们可以使用 Java8 Stream 的 `collect` 方法对集合进行分组求和,并使用 `...
2. 设计思路:定义两个类 Person 和 TestPerson,Person 类满足上述规定,TestPerson 类包含一个方法 public static void sortPerson(Person[] personList),在该函数中运用 Person 类的 older 方法实现对数组 ...
Java工具类是编程实践中不可或缺的一部分,它们提供了许多通用的功能,...以上就是Java工具类可能涉及的一些核心知识点,涵盖了Java开发中的多个方面。掌握这些工具类和相关概念,能够有效提升Java开发的效率和质量。
方法的重载(Overloading)是指在同一个类中定义多个同名方法,但参数列表不同。这有助于提高代码的可读性和复用性。 `return`不一定只在方法末尾使用,可以在满足某种条件时提前返回。 `switch`语句的表达式可以...
- `MyWindowListener` 类:这个类扩展了 `java.awt.event.WindowAdapter`,用于监听窗口事件。它覆盖了 `windowClosing` 方法,当用户尝试关闭窗口时,会调用 `System.exit(0)` 来结束程序运行。 - `ScaleFrame` ...
- **示例**:可变参数可以用于简化处理多个相同类型参数的方法,例如求和方法,可以接受任意数量的整数。 4. **Arrays工具类及API的使用**: - **Arrays类**:Java提供了一个内置的`java.util.Arrays`工具类,...
- 类中可以定义多个方法,方法和方法是平行的,不能在方法内部定义另一个方法。 - 方法中可以使用return关键字,它可以用来返回一个值给方法的调用者,也可以用来提前退出当前方法。 通过上述知识点的学习,零...
Java中的方法重载(Overload)是面向对象编程的一个重要特性,它允许我们在同一个类中定义多个具有相同名称但参数列表不同的方法。方法重载的关键在于“多态性”(Polymorphism),即同名方法可以通过不同的参数形式...
这份"java_java试题及答案.pdf"包含了多个关于Java技术的知识点,涵盖了基础语法、类与对象、异常处理、输入输出、图形用户界面(GUI)以及继承等多个方面。 1. **Java应用程序与Applet**: - Java Application的...
如果我们有一个User对象的List,并想计算所有User的年龄总和,我们可以使用Java 8的流API中的`summingInt()`方法: ```java List<User> users = ... // 初始化用户列表 int totalAge = users.stream() .collect...
1. Scanner类的应用:文件中多次出现import java.util.Scanner,表明程序中使用了Scanner类来从标准输入获取用户输入。Scanner类是Java的一个工具类,属于java.util包,提供了多种读取不同数据类型的方式。 2. 流程...
Lambda表达式主要用于实现接口中的抽象方法,尤其是那些只有一个抽象方法的接口,这类接口被称为函数式接口,例如`java.util.function.Consumer`、`java.util.function.Function`等。 ### 使用Lambda表达式简化代码...
这个简单的求和程序虽然基础,但它涵盖了软件开发中的多个核心概念,包括编程语言、用户界面设计、事件处理、数据运算以及异常管理等。通过深入理解这些知识点,开发者可以构建更复杂、功能丰富的应用。
它不仅涉及到软件开发的多个方面,包括面向对象设计、网络编程、GUI设计,还强调了性能需求在游戏开发中的重要性。通过这些知识点的分析与应用,开发人员能够设计出稳定、高效和用户友好的网络对弈平台。文档中的...