java十宗罪
java十宗罪
好吧,我知道看这标题很多人就忍不住要拍砖或表示不赞同了,我都接受。
我在遇到问题时,找一些搞java朋友求助,有能解决的,我想说的是不能解决的情况下,他们大多会说:“你怎么能这么弄呢?这么搞是不行的,你首先在思路上就错误了,我们从来就不这么做。”,比如“我们一般很少用存储过程,你用这么多存储过程,我建议你使用hibernate代码实现你的业务,而不是用存储过程”,这个问题是在我遇到用hibernate调存储过程时发生一些状况后,我一个搞java的朋友也无法解决时,他如此说道。
java开发人员还喜欢说:这个不应该由jdk或某某框架完成,而应该是由勇敢、勤劳、智慧的您来编写实现的。
以下都是我在开发java项目时,遇到的一些问题,可能也有写得不对的地方,望指正。
遇到很多问题,一时间无法全部拿出来讨论,就随便列举了几条。
1."abc"=="abc"返回的结果是false,很多初学java的都要在这个问题很浪费很多时间,因为会非常自信的以为这里会返回true,根本不会想到原来问题出在这里。网上看到有贴子讨论过这个问题,说什么java是纯面向对象的语言,==操作符是比较地址什么的,而"abc"是引用,所以不能使用==操作符进行比较,而应该使用equals方法来进行比较,会犯这种错误的,多半是因为自己基础不牢,却还来说java的不是。我看到一个人说的一个例子,很能表示我的感想,是这么说的:有一天我去到一个餐厅,因为餐厅门口有一滩水,导致路面很滑,我不小心摔倒了,于是我找来餐厅经理,追究其责任,结果餐厅经理告诉我,这是因为我自己走路的姿势不对,所以滑倒了,与餐厅无关。
2.为什么没有get;set;属性,而是使用getXX();setXX()方法来代替,反射难道不要成本吗?
我所了解到的struts\spring\hibernate里都大量用到这种方式,比如struts中的vo对象,里面若有个getUsername(),在页面里可以用<s:property value="username"/>来取值,这中间我想应该是用反射来找到getUsername()方法,再取得其值的吧,同样的spring\hibernate中也大量用到这种方式,我想问,反射不是说很低效的吗?
3.做个自定义标签还要自己写个tld配置文件,有时在看一些java的相关书籍上面提到零配置时,我就觉得非常可笑,不知道所谓零配置的精神到底体现在哪里?也许写个配置文件也并没有那么难,但关键问题在于,从技术上来讲这个tld明显是可以不要的啊,tld里面主要就描述了这个tag叫什么名字有哪些属性,分别是什么类型,这些信息完全可以在类里面表示,只要是实现Tag接口的类就被自动识别为自定义标签这样不好吗?通过识别类里有哪些getXX();setXX();(更好的方案是有get;set;属性)来确定这个自定义标签有哪些属性,又分别是什么类型这样不好吗?为什么还要多此一举搞个tld配置文件?
还有个问题是,如果我写了个MyTag的类,继承了某个自定义标签类,我还要为MyTag写个相应的tld配置,我不知道将来还有没有其他开发人员会继承我的MyTag,也许就算我热烈欢迎别人来继承我的MyTag,但当别人看到我MyTag里近三四十个getXX();setXX();之后,想到要为其写上相应的tld配置文件而望而生怯吧。
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配置文件了,但即使这样,据我了解依旧还是需要很多除连接字符串之外的其它的相关配置文件。
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(?,?,?,?)},这种方式显然也不是我想要的,我只想调用一个存储过程,执行一个业务的处理。以上两种方式是会被暗箱操作的事务所管理的,但并不能满足我的需求,我要怎么办?
6.数据访问的结果集对象ResultSet、RowSet、CachedRowSet等没有得到广泛的应用,各个框架更多的是倾向于支持实体列表,这么做导致出现一个问题,那就是我只能返回已知结构的结果集,若想要临时返回个东西还必须要在实体中添加相应的属性getXX();setXX();方法,比如在hibernate中,要访问员工表,员工表中本来只有部门ID,没有部门名称,你想要有部门名称,就必须在员工实体中添加一个deptName的属性,要所有的结果都是已知结构的,这样很痛苦,如果不返回到实体列表中,也可以返回到 ArrayList<Object[]> 中,但这样的数据没有列名称,不明白为什么不直接查询到ResultSet中,然后让更多的框架支持ResultSet,比如struts,在写页面使用struts标签时,可以像操作实体列表一样操作ResultSet。
<s:iterator id="myResultSet">...</s:iterator>,(还是本来就支持,只是我不会?那就不好意思啦!)只是希望让更多的框架支持未知结构的结果集,让程序员事先设计好结果集的结构是很累人的,就算是代码生成,也只能生成数据库里的每一张表对应的实体,但往往我们需要select unkownSchema from myTable得到未知结构的结果集,并不是每次都select *。
7.再说ResultSet,之所以不直接用这个,而使用实体列表来代替,我想是不是也间接的说明了,ResultSet这个类不方便使用,.net中的DataSet和DataTable就得到大量使用,因为它们方便好用实用。可能最大差别的地方就在于,DataSet是断开式的存在于内存中的微型数据库,而ResultSet只是连接式的数据库读取器,相当于.net中的DataReader,必须保持连接才能读数据,我知道有CachedRowSet可以断开式的存储数据在内存中,好吧,这个就不是问题了。但另一个问题在滋扰着我,做为存储结果集的容器,提供给我们操作这个结果集的方法太少了,甚至取得该结果集的总行数的方法,我们都需要开动小脑筋,这么写:rs.last(); int count = rs.getRow(); rs.first() 负责的话,它需要至少三句代码才能取到总行数。也许这只是小问题,这个或许应该由勇敢、勤劳、智慧的我们来实现。
8.在我看来,struts最大的意义在于,它使得每个jsp页面都有了一个与之对应的java类的方法,也就是那个action方法。你一定会跟我说,struts的功能并不只如此,但我说,我见过的很多(小公司)的项目,struts的意义就只是这样的,我想像在我们国家,还有成千上万的使用java技术的公司,struts对于他们的意义,也就是让jsp有了后台代码。如果仅仅只是如此,为何不由官方提供,直接让jdk支持,让struts的先进来弥补jdk的落后吗?只会欲盖弥彰。
或者你会说,即便struts就是提供了让每个jsp页面都有一个与之对应的action方法,这也非常伟大了,做到这一点,已经彻底改变了人们开发web项目的方式,由原来的业务代码和页面混在一起,变成解偶分离,非常成功了。我想说,不要拿你十年前的荣耀到今天再来说了,已经out的不行了。
9.再说myeclipse,这个ide在java体系中几乎成为标准,我见过的所有java开发人员都是使用这个IDE,但相比之下,它与visual studio就相差太多了,性能就不说了,如果不做优化,那是慢得想死,话说为什么不能在其一发布出来的默认设置就是最优化的呢?如果我们需要什么插件组件,再自己加载,这样不是更清楚明白吗?
另外myeclipse的插件安装方式实在让我汗颜,6.x,7.x,8.x这几个版本的插件安装方式各不相同,我在想,为什么不能直接双击安装?vss2005就是直接双击安装。至今我还没搞清楚svn插件怎么安装的,好吧,我是很水,那个插件的安装有时要复制文件到指定目录,有时要启动myeclipse之后,选择help菜单下的software updates,有时候又要选择什么myeclipse configuration center,有时候要连接互联网在线操作,更甚者,给你个java文件,要你编译成class文件,再按步骤操作,我是服了。
10.out输出参数,部分类,扩展方法,lamuda表达式这些非常好的东西,java都没有,还是我不会吗?望指正。
spring,其实我现在还不知道它是干嘛的,好吧,这是我的罪。
望展开激烈、火爆的讨论,可以使用分庭伉礼、围魏救赵、十面埋伏、单挑、围殴等各种手段。
[解决办法]
另外,我也表示不赞同把业务逻辑写进存储过程,小系统当然可以这么搞,如果业务量随时间递增,那么数据库的横向扩展能力是有限的,存储过程的压力全在数据库,到时不得不重构系统
如果把业务逻辑放到java程序,那么做集群,扩展就容易多了
[解决办法]
同意一部分,其他的不太懂
比如说结果集,当初我也想获取结果集的count,然后我就想当然的应该有一个getCount()或getRows()
TNND找死找不到
[解决办法]
这个东西返回啥貌似是和JVM的实现是有关系的。
String s1 = "abc";
String s2 = "abc";
s1==s2;//这个结果在不同的JVM下是不一样的
[解决办法]
我的程序里就没有框架,为什么要用框架呢?
框架也是乱七八糟的人写出来的,不是java官方出来的,水平参差不齐
我不用别人写的框架,我就用jdk自带的东西就OK了呗
[解决办法]
又不能怪HIBERNATE,我门可以选用别的方法连接数据库,
而且ECLIPSE的方式本来就是这样,用着用着就惯了,又不是很大问题,
不用十宗罪那么严重吧
[解决办法]
哪个svn插件? BTW,建议直接用eclipse for j2ee
框架的问题是这样。没有一个尽善尽美的框架。作为一个习惯了“自己动手,丰衣足食”的javaer,使用.NET也有不方便的时候,也有一大堆不满意的牢骚。可这并不影响.NET及其广大用户。
做多了项目,自然会总结出一套自己定制过的框架,也可能是基于SSH,也可能是不基于任何框架。.NET也一样,很多公司,时间久了也会有字节的控件库、框架的。
[解决办法]
主花那多心思研究西真是非常好
也有那多心思回 找一
10.out输出参数,部分类,扩展方法,lamuda表达式这些非常好的东西,java都没有,还是我不会吗?望指正。
spring,其实我现在还不知道它是干嘛的,好吧,这是我的罪。
首先要判java的,java是什麽?java的能不能代表java,因是一直在不展完善中的,我想java本身的那些相定的制才能真正代表java,或者java的理念
out出,利用出的形式行果出我得不太好,因它有直,方法返回值行果出比它要好,人性化地注程序者(程序)使其提高工作效率的理念我得是更受到肯定的,其整效率也是更高的,象言的流行就明了一,我不清楚部分类,扩展方法,lamuda表达式些是什麽,可能java有替代的吧,不清楚
[解决办法]
不是JAVA 不行,是楼主水平太次。
1。已经说过了,不重复。
2。getXX()只不过是JAVA Bean 规范,没人规定非得那样写。自己实现get(XXX)不就好了。
3。JSP Tag 2。0 可以不写tld
4。Hibernate 有SQLQuery。
5。Hibernate 有beginTransation等一系列事务控制,是你不会用。
6。Hibernate SQLQuery有addEntity和addScale方法,可以Mapping任意schema的结果集到实体或者List
7。楼主是不是不懂SQL?行数统计应该用SQL count()集合函数,关JAVA屁事。Count完,Hibernate query uniqueResult()拿结果呗
8。struts干JDK何事,JAVA的基本概念都不懂,在这纯扯淡。
9。别人说过了,花钱办事呗。
10。不知道你在说什么。这些JAVA都有,或是有等价替代方法,只是你菜而已。
[解决办法]
能否说说你用纯jdbc的思路呢?以前我也是想用纯jdbc,然后觉得太麻烦,就想着自己写些辅助方法,想着想着就觉得:我这样做了还不如去用hibernate了
[解决办法]
辅助方法dbutils这个小工具包里已经有了,其他的应该都差不多。我个人认为传统的那种dao方式不错
[解决办法]
我来替lz说句公道话:
public class test {
public static void main(String[] args) {
String str1 = new String("abc");
String str2 = new String("abc");
System.out.print(str1 == str2);
}
}
public class test {
public static void main(String[] args) {
String str1 = "abc";
String str2 = "abc";
System.out.print(str1 == str2);
}
}
大家看看这两个代码的执行结果,再批判lz,武断的批判lz,只能说明你们java基础更是半杯水,认为你还可以的话,把出现上面的原因解释下。
[解决办法]
语言、框架既然出现就有它存在的价值
如果你们有用过或者比较深入的了解某些语言或者框架、我绝的应该没有评论的资格
既然它还存在,还在被人们使用 那他一定有独到的地方
比如 臭豆腐,你乍一看 一闻,又丑又臭,当你品尝过,才知道到底怎么样(当然不同人口味不同)
既然觉得不好 1中选择 彻底放弃它 2就是去了解他 发现她的好!
[解决办法]
我是来捧楼主的~
[解决办法]
楼主,我支持你,就是你给的分太少了。否则我就帮你菜他们了。
[解决办法]
求草哥出手.我来给分.
[解决办法]
真给分吗?
1。
"abc" == "abc"
不会有一本讲Java的书告诉你它返回什么,它只会告诉你不要用==比较字符串。
语言标准不会规定这个东西。也就是说标准答案是“不知道”,回答true的是错的,回答false的也是错误的。
说Java这点设计不好的,是NB的!比如楼主!
2。 这个东西返回true和false,无所谓。因为Java程序员不能这么比,这么比基本等于没有意义。
3。
你知道Java1.1里面"abc" == "abc"也是返回true吗?
即使Java1.1这点返回true,那么Java 0.9也可能返回false。
完全看编译器怎么实现,你敢保证Android的Java也是返回true?
不要太自信而说楼主水平不行
4。
"abc" == "abc" =? 不是自诩看过点深入JVM吗?
如果我写一个.java文件,里面出现了 70000多个字符串常量怎么办?
CONSTANT_String_info {
u1 tag;
u2 string_index;
}
u2就是 unsigned short, 对70000这个数量的字符串常量,你们属性的常量池怎么处理?
每一个字符串常量都会在常量池内找到吗?
所以你最好回答 结果“未可知“
------解决方案--------------------
怎么个给法?
[解决办法]
对于IDE和各种优化,我也服了
另外,LZ给的分太少了,不足矣挑起战争,动机你懂的
[解决办法]
4。
"abc" == "abc" =? 不是自诩看过点深入JVM吗?
如果我写一个.java文件,里面出现了 70000多个字符串常量怎么办?
CONSTANT_String_info {
u1 tag;
u2 string_index;
}
u2就是 unsigned short, 对70000这个数量的字符串常量,你们属性的常量池怎么处理?
每一个字符串常量都会在常量池内找到吗?
所以你最好回答 结果“未可知“
"70000这个数量的字符串常量"是通不过编译滴。。。就是因为那个u2的限制,另外方法代码长度也是有限制的
[解决办法]
LZ,你态度真不错呢,你的原文我看了下,嘻嘻,http://www.cnblogs.com/zhouyou96/archive/2011/06/17/2083566.html
[解决办法]
Jacks测试套件检查Java编译器是否符合JLS。它由大量小测试案例组成,每个测试都侧重于JLS中特定的部分。通过生成带有指定编译行为的小测试案例,然后将每个案例的执行自动化,编译器作者或调试者可以快速找出Java源码到字节码转换中存在的问题。
只有通过兼容性测试的jvm才被认可,否则是伪java,而像“abc”=="abc"如果为false的话能通过么
[解决办法]
这个回复的不错:"abc"=="abc"这个问题应该是java最基础的吧,jvm为String这种类型专门设置了一个pool,目的是提升String的性能。
Java的精华是Java EE,不理解struts和spring是因为你还没有从一个整体架构上看一个系统,而只是站在语法的基本上审视。
如果你说.Net有DbHelper,那么Java就更NB。直接注入DataSource,除了分离配置文件外,JAVA还可以忽略数据库的类型,Java的开发人员根本不关心是Oracle还是DB2。
Java EE有JPA,操作存储过程没问题,hibernate也应该是支持JPA的,不知为何你说不支持存储过程。事务操作,Java EE有JTA,跟JPA结合起来用。
如果你要官方的struts,那么就是JSF,struts的作家就是jsf的架构师之一。
至于说为什么某些开源的构架没有包括在官方的技术之中,那说明你没有体会到Java世界真正精彩的地方——开源与创新。你看过JDK,应该知道Java EE相关的package里面都是接口和抽象类,官方并没有提供相应的实现。
就拿JSF来说,它的implementation就有oracle的adf、sun的Mojarra、Apache的MyFaces Core、JBoss的Seam等,这些implementation在兼容官方的基础上都有自己的特色和创新。
Java的世界百花齐放,而.Net的社区死气沉沉,看看那个codeplex,ASP的插件扩展,再比比同样JSF的Oracle ADF和JBoss Richfaces。
早前一个项目需要sftp传输文件,.net居然找不如一个免费的库,悲哀!
Java EE的精华之一是EJB,OOP讲究的是低耦合、高内聚,EJB就是这种思想的体现。所有的Bean都是container管理的,通过注入使用,一个bean不用关心其他bean的生命周期。熟练使用EJB才能体会到Java EE的精彩。而.net呢,去跟JAVA EE 4比吧
[解决办法]
你这十宗罪中有好多都是框架的,并不是 JAVA 的,呵呵。
[解决办法]
推荐一本书《Java解惑》
里面讲述了JAVA中95个神奇的“案件”
[解决办法]
看热闹,楼主还是比较深刻的,敢质疑是好的。
[解决办法]
为什么没有get;set;属性,而是使用getXX();setXX()方法来代替,反射难道不要成本吗?
这个怎么成了反射了?
明明就是方法调用吗,c#的属性实质还不是方法调用,可是c#为什么要搞出属性这种形式呢,这是我很纳闷的地方。
吃饭撑的
[解决办法]
关于你的第9条 讲ide的
我不得不说,vs 的功能和eclipse相比实在是差太多了
我随便说几个eclipse有的,vs里找不到的
outlook 类的大纲 ctrl+o
hi... 类层次 f4,ctrl+shift+h
open type 打开类型 ctrl+shift+t
open resource 打开资源 ctrl+shift+r
查找引用(是指程序的引用,而不是vs的字符串匹配) ctrl+g
...
你说上面的功能,vs里有吗?
如果有,我非常乐意知道,因为实在是很好用
另外,eclipse 只有100M的样子,myeclipse也1G不到
vs2010 却有好几G
[解决办法]
有时候java让我感觉就是一个中间件,在各种环境中转换语言的中间件。复杂功能和特效不行,底层也不行。
[解决办法]
我来分页。。。