社区编辑申请
注册/登录
细数Java十宗罪
开发 后端
Java开发人员还喜欢说:这个不应该由JDK或某某框架完成,而应该是由勇敢、勤劳、智慧的您来编写实现的。以下都是我在开发Java项目时,遇到的一些问题,可能也有写得不对的地方,望指正。遇到很多问题,一时间无法全部拿出来讨论,就随便列举了几条。

【纠正】非常抱歉,第1点关于"abc"=="abc"返回false是我搞错了,在java里是返回true的,我没有经过实验就这么说了,非常抱歉。之所以会这么说,是因为不记得是哪一种,因为我使用了==进行了字符串的比较,结果并没有返回我相要的结果,然后请教老人,老人们就训诫道:***使用equals进行比较,而不要使用==,故有此感慨。

【正文】好吧,我知道看这标题很多人就忍不住要拍砖或表示不赞同了,我都接受。

我在遇到问题时,找一些搞Java朋友求助,有能解决的,我想说的是不能解决的情况下,他们大多会说:“你怎么能这么弄呢?这么搞是不行的,你首先在思路上就错误了,我们从来就不这么做。”,比如“我们一般很少用存储过程,你用这么多存储过程,我建议你使用hibernate代码实现你的业务,而不是用存储过程”,这个问题是在我遇到用hibernate调存储过程时发生一些状况后,我一个搞Java的朋友也无法解决时,他如此说道。

Java开发人员还喜欢说:这个不应该由JDK或某某框架完成,而应该是由勇敢、勤劳、智慧的您来编写实现的。

以下都是我在开发Java项目时,遇到的一些问题,可能也有写得不对的地方,望指正。

遇到很多问题,一时间无法全部拿出来讨论,就随便列举了几条。

 

Top 1:"abc"=="abc"返回的结果是False,很多初学Java的都要在这个问题很浪费很多时间,因为会非常自信的以为这里会返回true,根本不会想到原来问题出在这里。网上看到有贴子讨论过这个问题,说什么Java是纯面向对象的语言,==操作符是比较地址什么的,而"abc"是引用,所以不能使用==操作符进行比较,而应该使用Equals方法来进行比较,会犯这种错误的,多半是因为自己基础不牢,却还来说Java的不是。我看到一个人说的一个例子,很能表示我的感想,是这么说的:有一天我去到一个餐厅,因为餐厅门口有一滩水,导致路面很滑,我不小心摔倒了,于是我找来餐厅经理,追究其责任,结果餐厅经理告诉我,这是因为我自己走路的姿势不对,所以滑倒了,与餐厅无关。

Top 2:为什么没有get;set;属性,而是使用getXX();setXX()方法来代替,反射难道不要成本吗?

我所了解到的Struts\Spring\Hibernate里都大量用到这种方式,比如Struts中的VO对象,里面若有个getUsername(),在页面里可以用来取值,这中间我想应该是用反射来找到getUsername()方法,再取得其值的吧,同样的Spring\Hibernate中也大量用到这种方式,我想问,反射不是说很低效的吗?

Top 3:做个自定义标签还要自己写个TLD配置文件,有时在看一些Java的相关书籍上面提到零配置时,我就觉得非常可笑,不知道所谓零配置的精神到底体现在哪里?也许写个配置文件也并没有那么难,但关键问题在于,从技术上来讲这个TLD明显是可以不要的啊,TLD里面主要就描述了这个tag叫什么名字有哪些属性,分别是什么类型,这些信息完全可以在类里面表示,只要是实现Tag接口的类就被自动识别为自定义标签这样不好吗?通过识别类里有哪些getXX();setXX();(更好的方案是有get;set;属性)来确定这个自定义标签有哪些属性,又分别是什么类型这样不好吗?为什么还要多此一举搞个TLD配置文件?

还有个问题是,如果我写了个MyTag的类,继承了某个自定义标签类,我还要为MyTag写个相应的TLD配置,我不知道将来还有没有其他开发人员会继承我的MyTag,也许就算我热烈欢迎别人来继承我的MyTag,但当别人看到我MyTag里近三四十个getXX();setXX();之后,想到要为其写上相应的TLD配置文件而望而生怯吧。

Top 4:数据访问在我看来,应该是个很简单的事情,简单来就,就是执行SQL语句,复杂一点,就再加上实体映射,所有框架解决的问题,首先就是要易于使用,在使用过Hibernate之后,我感觉它太复杂了,我在.NET里有一个数据访问层,只需要在指定的配置文件中配置连接字符串,就可以在程序中的任何地方调用DbHelper.Execute(sql)、DbHelper.ExecuteDataSet(sql)、DbHelper.ExecuteDataTable(sql)了,使用起来非常简单,当然也有实体映射,DbHelper.save(entity)、DbHelper.delete(entity or key)、DbHelper.select(条件)这一组方法就可以操作实体对象,Select返回的是实体列表,实体通过元属性设置其关联的表和字段,这中间除了连接字符串之外,是没有任何其它配置文件的。相比之下,Hibernate咋需要这么多配置文件?我知道Hibernate也可以配置注解,就不需了HBM配置文件了,但即使这样,据我了解依旧还是需要很多除连接字符串之外的其它的相关配置文件。

Top 5:话说Java也有这么多年了,Hibernate也有这么多年了,到底是我不会用,还是它真的就是这样的,Hibernate对于存储过程的支持,实在让我抓狂,居然不支持存储过程,在网上寻找Hibernate调用存储过程,得到的答案多数就是越过Hibernate,而仅仅从Hibernate中取得一个Connection,再使用JDBC的方式调用存储过程,这样做存在一个问题,事务不能得到控制了,由于我还比较水,Hibernate的事务控制又是暗箱操作的,好像是只要在Service层中写的业务代码就都在一个事务中,所以我无法让我的存储过程调用和Hibernate业务代码串在一个事务当中,而很多情况下,我是想要让它们一个失败就全部失败的。

除此之外,也有不越过Hibernate而调用存储过程的办法,有两个,也是要写配置文件,一个是必须要有返回的结果集,我就很纳闷,为什么一定要有结果集,我的很多存储过程就只是处理一些数据,不需要返回结果集的,最难受的是Oracle的存储过程其实不支持返回结果集,必须使用一种变态的游标方式返回,这么做我会感觉到极其反胃。另一个办法是通过修改实体在Insert\Update\Delete时的默认行为,比如我在Insert一个员工时,本来应该是执行SQL语句insert into employee values (?,?,?,?)的,我可以通过配置文件修改这个默认行为,改成{call myproc(?,?,?,?)},这种方式显然也不是我想要的,我只想调用一个存储过程,执行一个业务的处理。以上两种方式是会被暗箱操作的事务所管理的,但并不能满足我的需求,我要怎么办?

Top 6数据访问的结果集对象ResultSet、RowSet、CachedRowSet等没有得到广泛的应用,各个框架更多的是倾向于支持实体列表,这么做导致出现一个问题,那就是我只能返回已知结构的结果集,若想要临时返回个东西还必须要在实体中添加相应的属性getXX();setXX();方法,比如在Hibernate中,要访问员工表,员工表中本来只有部门ID,没有部门名称,你想要有部门名称,就必须在员工实体中添加一个deptName的属性,要所有的结果都是已知结构的,这样很痛苦,如果不返回到实体列表中,也可以返回到 ArrayList 中,但这样的数据没有列名称,不明白为什么不直接查询到ResultSet中,然后让更多的框架支持ResultSet,比如Struts,在写页面使用Struts标签时,可以像操作实体列表一样操作ResultSet。

...,(还是本来就支持,只是我不会?那就不好意思啦!)只是希望让更多的框架支持未知结构的结果集,让程序员事先设计好结果集的结构是很累人的,就算是代码生成,也只能生成数据库里的每一张表对应的实体,但往往我们需要select unkownSchema from myTable得到未知结构的结果集,并不是每次都Select *。

Top 7:再说ResultSet,之所以不直接用这个,而使用实体列表来代替,我想是不是也间接的说明了,ResultSet这个类不方便使用,.NET中的DataSet和DataTable就得到大量使用,因为它们方便好用实用。可能***差别的地方就在于,DataSet是断开式的存在于内存中的微型数据库,而ResultSet只是连接式的数据库读取器,相当于.NET中的DataReader,必须保持连接才能读数据,我知道有CachedRowSet可以断开式的存储数据在内存中,好吧,这个就不是问题了。但另一个问题在滋扰着我,做为存储结果集的容器,提供给我们操作这个结果集的方法太少了,甚至取得该结果集的总行数的方法,我们都需要开动小脑筋,这么写:rs.last(); int count = rs.getRow(); rs.first() 负责的话,它需要至少三句代码才能取到总行数。也许这只是小问题,这个或许应该由勇敢、勤劳、智慧的我们来实现。

Top 8在我看来,Struts***的意义在于,它使得每个JSP页面都有了一个与之对应的Java类的方法,也就是那个Action方法。你一定会跟我说,Struts的功能并不只如此,但我说,我见过的很多(小公司)的项目,Struts的意义就只是这样的,我想像在我们国家,还有成千上万的使用Java技术的公司,Struts对于他们的意义,也就是让JSP有了后台代码。如果仅仅只是如此,为何不由官方提供,直接让JDK支持,让Struts的先进来弥补JDK的落后吗?只会欲盖弥彰。

或者你会说,即便Struts就是提供了让每个JSP页面都有一个与之对应的Action方法,这也非常伟大了,做到这一点,已经彻底改变了人们开发Web项目的方式,由原来的业务代码和页面混在一起,变成解偶分离,非常成功了。我想说,不要拿你十年前的荣耀到今天再来说了,已经Out的不行了。

Top 9再说MyEclipse,这个IDE在Java体系中几乎成为标准,我见过的所有Java开发人员都是使用这个IDE,但相比之下,它与Visual Studio就相差太多了,性能就不说了,如果不做优化,那是慢得想死,话说为什么不能在其一发布出来的默认设置就是***化的呢?如果我们需要什么插件组件,再自己加载,这样不是更清楚明白吗?

另外MyEclipse的插件安装方式实在让我汗颜,6.x,7.x,8.x这几个版本的插件安装方式各不相同,我在想,为什么不能直接双击安装?VS2005就是直接双击安装。至今我还没搞清楚svn插件怎么安装的,好吧,我是很水,那个插件的安装有时要复制文件到指定目录,有时要启动MyEclipse之后,选择Help菜单下的Software Updates,有时候又要选择什么MyEclipse configuration center,有时候要连接互联网在线操作,更甚者,给你个Java文件,要你编译成Class文件,再按步骤操作,我是服了。

Top 10Out输出参数,部分类,扩展方法,LAMUDA表达式这些非常好的东西,Java都没有,还是我不会吗?望指正。

我的罪:Spring,其实我现在还不知道它是干嘛的,好吧,这是我的罪。

原文链接:http://www.cnblogs.com/zhouyou96/archive/2011/06/17/2083566.html

【编辑推荐】

  1. Java轻量级中间件服务器:SIwpas
  2. Java编程语言基础JSP基本语法的详细介绍
  3. 如何用Java操作MongoDB
  4. Java泛型简明教程
  5. 向Java开战?别搞错了对象
责任编辑:艾婧 来源: zhouyou96的博客
相关推荐

2022-05-17 14:03:42

勒索软件远程工作

2022-05-07 10:09:01

开发Java日志

2022-04-13 08:00:00

Hilla开发Java

2022-03-31 07:52:01

Java多线程并发

2022-05-20 08:17:43

Java日志

2022-05-10 16:04:40

编程语言PythonC语言

2022-04-20 10:56:06

JavaJVM参数

2022-04-08 08:26:03

JavaHTTP请求

2022-04-28 15:38:42

WebViewJavaUI

2022-04-17 23:09:07

深度学习人工智能芯片

2022-04-07 10:39:21

反射Java安全

2022-05-09 11:52:38

Java卡片服务卡片

2022-05-13 11:02:45

数据中心配电设计

2022-04-03 19:51:38

linux服务性能

2022-03-31 15:17:04

JavaSocketServlet容器

2022-04-25 11:26:16

开发SpringBoot

2022-04-20 07:48:09

微服务链路服务器

2022-04-11 07:50:58

2022-04-19 11:09:13

Wi-Fi IoT智能小车鸿蒙

2022-03-22 07:57:42

Java多线程并发

同话题下的热门内容

简单的六种防止数据重复提交的方法!用Python进行人脸识别「包括源代码」超实用!教你用 Python 获取并下载美股数据在 Go 中实现一个支持并发的 TCP 服务端Python或R:哪种编程语言更适合数据科学?用 XML 和 Java 构建树莓派打印机的用户界面C语言:如何给全局变量起一个别名?什么!Sentinel流控规则可以这样玩?

编辑推荐

使用Kotlin做开发一个月后的感想面试官问你什么是消息队列?把这篇甩给他!五大自动化测试的Python框架图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS)2018年最流行的十大编程语言,其中包括你用的语言吗?
我收藏的内容
点赞
收藏

51CTO技术栈公众号