`
rensanning
  • 浏览: 3515146 次
  • 性别: Icon_minigender_1
  • 来自: 大连
博客专栏
Efef1dba-f7dd-3931-8a61-8e1c76c3e39f
使用Titanium Mo...
浏览量:37503
Bbab2146-6e1d-3c50-acd6-c8bae29e307d
Cordova 3.x入门...
浏览量:604411
C08766e7-8a33-3f9b-9155-654af05c3484
常用Java开源Libra...
浏览量:678182
77063fb3-0ee7-3bfa-9c72-2a0234ebf83e
搭建 CentOS 6 服...
浏览量:87338
E40e5e76-1f3b-398e-b6a6-dc9cfbb38156
Spring Boot 入...
浏览量:399875
Abe39461-b089-344f-99fa-cdfbddea0e18
基于Spring Secu...
浏览量:69090
66a41a70-fdf0-3dc9-aa31-19b7e8b24672
MQTT入门
浏览量:90519
社区版块
存档分类
最新评论

那些丑陋的Java API

    博客分类:
  • Java
 
阅读更多
Java语言自从1995年正式推出以来,已经成为被广泛采用的编程语言之一。在TIOBE编程语言排行榜榜单上也一直保持着前几名的位置。

《Java: The Good Parts / Java语言精粹》一书中,SUN的工程师更是大加赞扬了Java在各个方面的优点,其实Java存在很多Bad Parts需要改善。有时候开发者只是需要一个很简单的支持,但是SUN(如今是Oracle)的大师们却需要我们死很多脑细胞才能实现我们想要的。

Tiago Fernandez曾经做过一个很有意思的投票,统计对Java API的不满意程度,EJB2.x、Date/Time/Calendar、XML/DOM、AWT/Swing、EJB3.x、Mail、Servlet/JSP、I/O等均上榜。让我们来看看这些“丑陋的Java API”吧!

(1)臭名昭著的EJB
这个就不多说了。虽然EJB3.x有所改善,但是开发者更能接受Spring了。

(2)日期处理
Java中的日期处理API是被所有的开发者深恶痛绝的!最初使用java.util.Date实现,包含了日期与时间,但是无法实现国际化。更奇怪的是属性的偏移量,月份与小时都是基于0,月份中的天数则是基于1,而年则是从1900开始的。而随着JDBC的发布,又诞生了一个java.sql.Date,它继承自java.util.Date,但却有不同的含义。IBM在1998年贡献了一个java.util.Calendar,实现了国际化,但却更复杂。

// Return Last Day of a Month "2013/4/8"
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2013);
calendar.set(Calendar.MONTH, 4 - 1);
calendar.set(Calendar.DATE, 8);
calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
// calendar.add(Calendar.DATE, -1);

Date dd = cal.getTime();

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
String lastDay = sdf.format(dd);


2005年,Stephen Colebourne发布Joda-Time库,这个库非常流行并且得到了广泛的使用。Stephen Colebourne领导的JSR 310: Date and Time API已经被添加到了Java 8的特性列表中,期待有所改善吧!

http://stackoverflow.com/questions/6841333/why-is-subtracting-these-two-times-in-1927-giving-a-strange-result
http://stackoverflow.com/questions/15629222/java-sql-timestamp-comparison-bug
http://stackoverflow.com/questions/13141123/java-sql-timestamp-created-from-java-util-date-why-always-before-it

(3)异常捕获
比如以下一个简单的反射获取字段值,需要捕获4个不同的异常:
Field field;
try {
	
	field = getClass().getField("testField");
	Object value = field.get(this);
	
} catch (SecurityException e) {
	e.printStackTrace();
} catch (NoSuchFieldException e) {
	e.printStackTrace();
} catch (IllegalArgumentException e) {
	e.printStackTrace();
} catch (IllegalAccessException e) {
	e.printStackTrace();
}

类似的API包括:反射API、RMI API、JDBC API、 JAXP等Xml相关API、J2EE相关API(JNDI/EJB2/JMS/JavaMail等)等等。
很多开发者不得不捕获所有的Exception和Throwable。

XStream Thoughtworks的开源产品,采用的是xpp来进行xml和Java对象之间的转换。它不需要schema或其他的mapping文件就可以进行java对象和xml文件之间的转换,API调用起来非常方便,并且扩展功能强大。

Java 7 支持多异常捕获:
Field field;
try {
	
	field = getClass().getField("testField");
	Object value = field.get(this);
	
} catch (SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
	e.printStackTrace();
}


(4)资源释放
在发生异常时,如果想释放资源,我们不得不先做空判断,然后再关闭,而关闭的时候还有可能继续发生异常:
Reader in = null;

try {
    in = new BufferedReader(new FileReader("文件名"));

    
} catch (IOException e) {

} finally {
    if (in != null) {
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


Java 7支持 try-with-resources
private static void customBufferStreamCopy(File source, File target) {
    try (InputStream fis = new FileInputStream(source);
        OutputStream fos = new FileOutputStream(target)){
       
        byte[] buf = new byte[8192];

        int i;
        while ((i = fis.read(buf)) != -1) {
            fos.write(buf, 0, i);
        }
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}


(5)精度计算
在财务计算的系统中经常会使用到精度计算。Java做大数的精度操作需要用到java.math.BigDecimal和java.text.DecimalFormat。在《Effective Java》这本书中也提到这个原则,float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用java.math.BigDecimal。

由于Java没有运算符重载的支持,简单的乘法也不得不写成以下这个样子:
BigDecimal num1 = new BigDecimal("123456.789");
BigDecimal num2 = new BigDecimal("111.111");

BigDecimal result = num1.multiply(num2);


Java中long的最大值是2的63次方减1,如果你想定义一个超过int上限的long
long a = 9223372036854775807; // NG [The literal 9223372036854775807 of type int is out of range]


可以加个“L”:
long a = 9223372036854775807L; // OK


同样的有long-L、double-d、float-f。不知道为什么就不支持大数的精度计算呢。

(6)字符串处理
字符串处理应该是程序中使用最频繁的了,但Java提供的String方法太过于局限,虽然有StringTokenizer但是使用太复杂,所以往往我们不得不使用Commons Lang的StringUtils或者去写自己的StringUtils。
java.lang.String / java.util.StringTokenizer
java.lang.StringBuffer / java.lang.StringBuilder

Apache Commons补充了很多Java的不足,很多开源软件都默认依赖它。http://commons.apache.org/

(7)基本类型和包装类
int/Integer、double/Double等共存,代码中不得不充斥着各种各样的Integer.parseInt()、Integer.valueOf()。而Java5.0开始提供基本数据(Primitive)类型的自动装箱(autoboxing)、拆箱(unboxing) ,但对于我们经常处理的比如NOT NULL限制的DB字段,很容易发生NullPointerException。

而Map、List、Set集合类中又无法使用基本型,不得不再导入比如:Trove、Google Guava等lib。

(8)数组与集合
比如取个长度,数组用的属性array.length,而集合用的方法list.size()。

泛型:
public class Test<T> {
	public Test() {
		List<T> list = new ArrayList<T>(); // OK
		T[] array = new T[3]; // NG [Cannot create a generic array of T]
	}
}

Scala创始人Martin Odersky说当年正是因为Java泛型的丑陋才创建了Scala。

赋值转换:
String[] strArray = null;
Object[] objArray = null;
List<String> strList = null;
List<Object> objList = null;
	
objArray = strArray; // OK
objList = strList; // NG [Type mismatch: cannot convert from List<String> to List<Object>]


集合转数组:
比如:ArrayList.toArray();
ArrayList<String> stock_list = new ArrayList<String>();
stock_list.add("stock1");
stock_list.add("stock2");

String[] stockArr1 = stock_list.toArray(); // NG [Type mismatch: cannot convert from Object[] to String[]]
String[] stockArr2 = stock_list.toArray(new String[stock_list.size()]); // OK
String[] stockArr3 = stock_list.toArray(new String[0]); // OK
String[] stockArr4 = stock_list.toArray(new String[stock_list.size() + 10]); // OK

需要注意的是stockArr2和stockArr3(重新创建了一个数组返回)能正常返回我们想要的数据,但是stockArr4返回的数组长度为12,除过前两位以外都是null。

集合类不支持基本类型:
还是需要借助Trove、Google Guava等开源代码

(9)日志
Java诞生后不久log4j就发布了,并且得到了广大程序员的支持,但SUN死活不肯接受log4j 非要自己搞个log框架,自JDK 1.4发布java.util.logging日志包一来直到现在Java 1.7,许多开发者依然使用log4j或者通用的日志工具,而不是使用JDK logger。
JSR-047(Logging API Specification)

还有一些正在起草当中的JSR:
JSR 317: Java Persistence 2.0(替代Hibernate)
JSR 107: JCACHE - Java Temporary Caching API(替代EhCache)
JSR 353: JavaTM API for JSON Processing (阿里的温绍锦是该JSR的专家组成员)
......
Java的规范是有名的多而且复杂,有兴趣大家可以看看http://jcp.org/en/jsr/all,目前都排到JSR 362了。

(10)一些易错的API
比如:
  File.mkdir()方法
  String.equals()方法
  以对象为Key的Map
  ......

当然,任何语言都不会是完美的,编程语言也都在不断的进化当中。Java中也还有很多相当优秀的API,比如,Doug Lea大师的java.util.concurrent包(JSR 166: Concurrency Utilities),就是功能齐全,性能卓越,优秀完美的并发库。互联网进入大数据处理时代,更加突显这个并发库的重要性。

补充:
1:文中不涉及到类似“泛型”等这种语法糖的问题。只探讨那些常用但是又易错,难用的API。
2:文中不涉及类似Java不支持多继承,没有const关键字等语法上的问题。
3:追加一下Joshua Bloch 的《Java Puzzlers: Traps, Pitfalls, and Corner Cases/Java解惑》希望对大家有所帮助!


参考资料:
http://stackoverflow.com/questions/238173/worst-java-practice-found-in-your-experience
http://www.youtube.com/watch?v=hcY8cYfAEwU
http://d.hatena.ne.jp/ryoasai/20110226/1298703499
http://dev.sei.pku.edu.cn/trac/pkuas/blog/2011/04/06/zhanglei09/my_topic
http://www.cnblogs.com/dushu/archive/2013/01/18/2866379.html
http://www.raychase.net/1098
25
6
分享到:
评论
42 楼 SE_XiaoFeng 2013-07-19  
看评论看的我心情澎湃,感谢博主写出这样的好文章.
41 楼 alvin198761 2013-04-11  
alvin198761 写道
ansjsun 写道
alvin198761 写道

1.dom4j你比过没有,有数据结论没有?
3.我有说java只有正则?
4.什么是api,这东西提供出来了就不能更改,只能改底层,上层提供的接口必须按照老样子去做,不然会导致不兼容,io在很多年前就写了,后起的语言必然知道,而出来的早的,为了兼容从前的版本,自然不能更改以前的api接口,底层确实重写了,但是如果他把上层的写法变了,以前的代码必然不兼容了,这个你都不懂,新增加的内容没有这种问题就对了,老的东西必须沿用,这是api躲不过去的
--在指责java的时候,难道不该站在java当时的情况综合考虑?


1.我要没比过我不会和你说的.而且学java的时候就用jdk自带的解析xml.dom,sax解析.几行代码..如果你要是有什么能比dom4j优雅的写法欢迎发出来毁我三观,话有说回来..现在我们用xml已经很少了.一般都用json来做了..

2.你漏掉了...

3可惜你的那句原话找不到了..你回忆下吧.

4.api提供出来就不能更改?谁规定的..是应该有向下兼容.但是有些方法还是有@Deprecated的.io的不方便并不是因为api不可修改好不..你自己包装也方便不到哪里去..这是..java语言的语法决定的..比如python 可以这么写
for line in file :
java不管怎么包装也写不了的..

还有..我说nio 是因为你嘲笑楼主不知道nio...和这个又没什么关系...

api的伤都属于软伤..现在很多好的工具包..比如guava  apache那个工具包其实都比较适用..但是大家还是希望能在java未来的版本中..有所改进..甚至是语法上面的改进


好了..这是我最后一次回复你了.可以结束了..

代码的不优雅难道不是你自己造成的,文件操作这样不就好了?
public void copy(File srcFil, File targetFile) {
        try {
            RandomAccessFile sf = new RandomAccessFile(srcFil, "r");
            RandomAccessFile tf = new RandomAccessFile(targetFile, "rws");
            FileChannel sfcChannel = sf.getChannel();
            FileChannel tfcChannel = tf.getChannel();
            tfcChannel.transferFrom(sfcChannel, 0, sfcChannel.size());
        } catch (IOException ex) {
            Logger.getLogger(TimeTest.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void move(File srcFil, File targetFile) {
        srcFil.renameTo(targetFile.getParentFile());
    }
---
你对jdk的xml稍微封装一下会不?一个封装类足矣,
一个不懂艺术的人,站在艺术品面前觉得什么都是多余的。我也不再回你的信息了

刚刚代码手写的,没测试,只是想说明问题
40 楼 windshome 2013-04-11  
Java自带的API的确值得争议的地方很多,见仁见智,随着Java版本的不断提升,API越来越多,与之相应的,使用不便之处、各种问题也是越来越多,更何况符合不同人的口味,所以,使用者也是提出一些自己的看法而已。

有时候,API做出来,不大好用,文档描述还不清晰,让使用者掉进坑里后才明白,“原来是这样啊”,Java有很多这种情况,我也深有体会,要不,API设计得易用性好一些,要不,文档说清楚一些,都会好很多。这其实也是人与人沟通理解上的问题,人和人水平不一样,文字方式和风格不一样,自然会带来诸如此类的问题。

我觉得,我之前提出的那个Java建立Socket的问题,的确是Java设计者考虑问题时不是非常周详造成的,详细的描述请大家看我的文章[url] http://windshome.iteye.com/blog/1836885[/url]
39 楼 alvin198761 2013-04-11  
ansjsun 写道
alvin198761 写道

1.dom4j你比过没有,有数据结论没有?
3.我有说java只有正则?
4.什么是api,这东西提供出来了就不能更改,只能改底层,上层提供的接口必须按照老样子去做,不然会导致不兼容,io在很多年前就写了,后起的语言必然知道,而出来的早的,为了兼容从前的版本,自然不能更改以前的api接口,底层确实重写了,但是如果他把上层的写法变了,以前的代码必然不兼容了,这个你都不懂,新增加的内容没有这种问题就对了,老的东西必须沿用,这是api躲不过去的
--在指责java的时候,难道不该站在java当时的情况综合考虑?


1.我要没比过我不会和你说的.而且学java的时候就用jdk自带的解析xml.dom,sax解析.几行代码..如果你要是有什么能比dom4j优雅的写法欢迎发出来毁我三观,话有说回来..现在我们用xml已经很少了.一般都用json来做了..

2.你漏掉了...

3可惜你的那句原话找不到了..你回忆下吧.

4.api提供出来就不能更改?谁规定的..是应该有向下兼容.但是有些方法还是有@Deprecated的.io的不方便并不是因为api不可修改好不..你自己包装也方便不到哪里去..这是..java语言的语法决定的..比如python 可以这么写
for line in file :
java不管怎么包装也写不了的..

还有..我说nio 是因为你嘲笑楼主不知道nio...和这个又没什么关系...

api的伤都属于软伤..现在很多好的工具包..比如guava  apache那个工具包其实都比较适用..但是大家还是希望能在java未来的版本中..有所改进..甚至是语法上面的改进


好了..这是我最后一次回复你了.可以结束了..

代码的不优雅难道不是你自己造成的,文件操作这样不就好了?
public void copy(File srcFil, File targetFile) {
        try {
            RandomAccessFile sf = new RandomAccessFile(srcFil, "r");
            RandomAccessFile tf = new RandomAccessFile(targetFile, "rws");
            FileChannel sfcChannel = sf.getChannel();
            FileChannel tfcChannel = tf.getChannel();
            tfcChannel.transferFrom(sfcChannel, 0, sfcChannel.size());
        } catch (IOException ex) {
            Logger.getLogger(TimeTest.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void move(File srcFil, File targetFile) {
        srcFil.renameTo(targetFile.getParentFile());
    }
---
你对jdk的xml稍微封装一下会不?一个封装类足矣,
一个不懂艺术的人,站在艺术品面前觉得什么都是多余的。我也不再回你的信息了
38 楼 dongruan00 2013-04-11  
37 楼 ansjsun 2013-04-10  
alvin198761 写道

1.dom4j你比过没有,有数据结论没有?
3.我有说java只有正则?
4.什么是api,这东西提供出来了就不能更改,只能改底层,上层提供的接口必须按照老样子去做,不然会导致不兼容,io在很多年前就写了,后起的语言必然知道,而出来的早的,为了兼容从前的版本,自然不能更改以前的api接口,底层确实重写了,但是如果他把上层的写法变了,以前的代码必然不兼容了,这个你都不懂,新增加的内容没有这种问题就对了,老的东西必须沿用,这是api躲不过去的
--在指责java的时候,难道不该站在java当时的情况综合考虑?


1.我要没比过我不会和你说的.而且学java的时候就用jdk自带的解析xml.dom,sax解析.几行代码..如果你要是有什么能比dom4j优雅的写法欢迎发出来毁我三观,话有说回来..现在我们用xml已经很少了.一般都用json来做了..

2.你漏掉了...

3可惜你的那句原话找不到了..你回忆下吧.

4.api提供出来就不能更改?谁规定的..是应该有向下兼容.但是有些方法还是有@Deprecated的.io的不方便并不是因为api不可修改好不..你自己包装也方便不到哪里去..这是..java语言的语法决定的..比如python 可以这么写
for line in file :
java不管怎么包装也写不了的..

还有..我说nio 是因为你嘲笑楼主不知道nio...和这个又没什么关系...

api的伤都属于软伤..现在很多好的工具包..比如guava  apache那个工具包其实都比较适用..但是大家还是希望能在java未来的版本中..有所改进..甚至是语法上面的改进


好了..这是我最后一次回复你了.可以结束了..
36 楼 ansjsun 2013-04-10  
alvin198761 写道

这句话就是对java程序员的歧视,
我一直是做产品的,我可以明确告诉你,
语言我不一定懂的比你少,任何语言也都有不足的地方,
我的公司对代码规范做的很好,我自然就没有看到那些,一个方法里面的大括号都不会超过两层,api并不丑陋,只是写代码的人写出了丑陋的代码而已,提供给你一个平台,你写的好看,代码自然就好看,写的丑陋,代码自然就丑陋,我这里举个例子
代码如下:
if(a){
  if(b){
   if(c){
     if(d){
      //code
     }
   }
  }
}
//这个代码丑陋,但是我公司要求的写法有这两种:
1.
if(a)return;
if(b)return;
if(c)return;
if(d){code};

//
2.

do{
  if(a) break;
  if(b) break;
  if(c) break;
  if(d) code;
}while(false);
------------------
是不是同样的api?
丑陋的不是api吧,是写代码的人而已


额..原来是做产品的...是产品经理还是你么的的软件当产品卖??要是产品经理我原谅你了..

1.这种写法
if(a)return;
if(b)return;
if(c)return;
if(d){code};
----
可以考虑下 switch case.别说不支持string..jdk7 支持了...而且enum 也可以

另外...
if(a){
  if(b){
   if(c){
     if(d){
      //code
     }
   }
  }
}

这个代码和上面那个有什么关系??

你要是改写应该写成 if(a&&b&&c&&d) 吧


我估计你想给我举例嵌套for循环是吧..


再说你第二个方法

do{
  if(a) break;
  if(b) break;
  if(c) break;
  if(d) code;
}while(false);


do while 其实不怎么提倡用了..用的比较少..除非高性怪需求方面..其他还是正经写吧

我看了半天没看明白...这个代码的意思

直接一个 if(d){ code };

就可以了吧...我没有理解你要表达什么..


真替你们公司担心...我但愿你你举例举错了..或者我鸡蛋里面挑骨头...!!!!

35 楼 damoqiongqiu 2013-04-10  
2.

do{
  if(a) break;
  if(b) break;
  if(c) break;
  if(d) code;
}while(false);


话说,这写法挺奇葩
34 楼 alvin198761 2013-04-10  
ansjsun 写道
回复:alvin198761

alvin198761 写道
......


职业喷子..3年java气急败坏....




这句话就是对java程序员的歧视,
我一直是做产品的,我可以明确告诉你,
语言我不一定懂的比你少,任何语言也都有不足的地方,
我的公司对代码规范做的很好,我自然就没有看到那些,一个方法里面的大括号都不会超过两层,api并不丑陋,只是写代码的人写出了丑陋的代码而已,提供给你一个平台,你写的好看,代码自然就好看,写的丑陋,代码自然就丑陋,我这里举个例子
代码如下:
if(a){
  if(b){
   if(c){
     if(d){
      //code
     }
   }
  }
}
//这个代码丑陋,但是我公司要求的写法有这两种:
1.
if(a)return;
if(b)return;
if(c)return;
if(d){code};

//
2.

do{
  if(a) break;
  if(b) break;
  if(c) break;
  if(d) code;
}while(false);
------------------
是不是同样的api?
丑陋的不是api吧,是写代码的人而已
33 楼 alvin198761 2013-04-10  
dom4j
ansjsun 写道
回复:alvin198761

alvin198761 写道
......


职业喷子..3年java气急败坏....

1.你用jdk自带的和 dom4j 写起来比比就知道了.

2.数组那个其实jdk7已经处理了..那个问题很困惑程序员...Object[] 无法转型..你要没遇到过.只能说你代码写的不够

3.tonker String类..的确用的人不多..其实java挺强大的..你认为string只有正则么?

5.io关流代码的确不优雅..jdk7 已经处理了.. 至于nio ...其实 jdk的io已经用nio重写了..建议你看看jdk源码去


6.注意下论坛秩序.楼主提出的这些问题的确是jdk中存在的..有的已经修复..有的还有..比如日期类一直让人不爽.

还有 alvin198761  你可以多看看其他语言..做比较...比如python 对io 文件读写的方式...

也可以看看java 的guava包...  希望你能有点收获...




1.你比过没有,有数据结论没有?
3.我有说java只有正则?
4.什么是api,这东西提供出来了就不能更改,只能改底层,上层提供的接口必须按照老样子去做,不然会导致不兼容,io在很多年前就写了,后起的语言必然知道,而出来的早的,为了兼容从前的版本,自然不能更改以前的api接口,底层确实重写了,但是如果他把上层的写法变了,以前的代码必然不兼容了,这个你都不懂,新增加的内容没有这种问题就对了,老的东西必须沿用,这是api躲不过去的
--在指责java的时候,难道不该站在java当时的情况综合考虑?
32 楼 jorneyR 2013-04-10  
rensanning 写道
本文初衷并不在于贬低Java或者全盘否定Java API,文中也已经补充了“有点儿标题党”;也无意于和其他语言进行比较,要不然就会给出各个问题点的其他语言(Groovy、Scala)的实现方式了。大家也都很反感语言之间的比较,因为各个语言都有自己的优劣,凡是一提到语言比较的话题都能激起一场无休止的讨论,萝卜白菜各有所爱。但是必须承认的是任何语言都有自己的弱项,比如stackoverflow上还有关于PHP的讨论,如果有PHPer的朋友也可以看看http://stackoverflow.com/questions/233030/worst-php-practice-found-in-your-experience,本文的参考资料中也列出了一些观点的来源,并非个人一厢情愿。

真正的目的是能总结在Java开发过程中那些易错,难用的API。在开发中,除去那些业务上的Bug外,很多时候出现问题的都是一些不经意的API的误用,比如不该catch的catch了、该判空的没有判空等等(当然这些也可以通过使用Checkstyle、FindBugs、PMD、JTest等静态分析工具来避免那就是另外一个话题了)。如果有心的开发者可以统计一下自己过往的Bug分类,很多时候困惑自己的往往是一些基本的东西。


楼主脾气真好,昨天说这话的时候心里正烦,说得不客气了些,^_^,不好意思。
31 楼 yuankai 2013-04-10  
确实这些问题都碰到了,总结的不错。
那个log真的是太不好用了,真的早就该统一。
30 楼 rensanning 2013-04-10  
successfulroof 写道
successfulroof 写道
订正一下吧,免得误人。java.util.Date开始时间不是1900
new Date(long time); time可以为负的,自己试试吧


-62135798399000 这是0001年01月01号

这里说的相对1900年指的是Date(year, month, date)。我们需要的不应该是一个这样的API吗。
29 楼 xiaozhi6156 2013-04-09  
不错,确实这些类又错,又经常忘记
28 楼 damoqiongqiu 2013-04-09  
文章总体是非常不错的
作者本意也不是为了喷Java
如果不是对Java有深切的了解,也无法对Java API里面的诸多弊端总结得如此全面
至于那些为喷而喷的狂热分子,就缩在你的井底对着月亮喷口水吧
某老外有本书更加激进,貌似叫《Java的末日》?N年前刚开始学Java的时候看过,比较刺激

27 楼 damoqiongqiu 2013-04-09  
guwei999 写道
damoqiongqiu 写道
漏掉了<泛型>这块鸡肋


public interface BaseDAO<T, ID extends Serializable> {

public void save(T entity);

public void update(T entity);

public T get(ID id);

}


看看这个接口,泛型鸡肋吗?我怎么没觉得啊……


也许你需要看看C++的泛型和模板方法
然后和Java这里比一比
小僧搞Java也快七年有余
越来越觉得Java这种泛型完全是在走邪路
26 楼 guwei999 2013-04-09  
damoqiongqiu 写道
漏掉了<泛型>这块鸡肋


public interface BaseDAO<T, ID extends Serializable> {

public void save(T entity);

public void update(T entity);

public T get(ID id);

}


看看这个接口,泛型鸡肋吗?我怎么没觉得啊……
25 楼 successfulroof 2013-04-09  
successfulroof 写道
订正一下吧,免得误人。java.util.Date开始时间不是1900
new Date(long time); time可以为负的,自己试试吧


-62135798399000 这是0001年01月01号
24 楼 successfulroof 2013-04-09  
订正一下吧,免得误人。java.util.Date开始时间不是1900
new Date(long time); time可以为负的,自己试试吧
23 楼 rensanning 2013-04-09  
本文初衷并不在于贬低Java或者全盘否定Java API,文中也已经补充了“有点儿标题党”;也无意于和其他语言进行比较,要不然就会给出各个问题点的其他语言(Groovy、Scala)的实现方式了。大家也都很反感语言之间的比较,因为各个语言都有自己的优劣,凡是一提到语言比较的话题都能激起一场无休止的讨论,萝卜白菜各有所爱。但是必须承认的是任何语言都有自己的弱项,比如stackoverflow上还有关于PHP的讨论,如果有PHPer的朋友也可以看看http://stackoverflow.com/questions/233030/worst-php-practice-found-in-your-experience,本文的参考资料中也列出了一些观点的来源,并非个人一厢情愿。

真正的目的是能总结在Java开发过程中那些易错,难用的API。在开发中,除去那些业务上的Bug外,很多时候出现问题的都是一些不经意的API的误用,比如不该catch的catch了、该判空的没有判空等等(当然这些也可以通过使用Checkstyle、FindBugs、PMD、JTest等静态分析工具来避免那就是另外一个话题了)。如果有心的开发者可以统计一下自己过往的Bug分类,很多时候困惑自己的往往是一些基本的东西。

相关推荐

    working-gym-java-client:一个Java客户端来访问OpenAI Gym HTTP服务器

    OPEN AI GYM HTTP服务器的JAVA CLIENT 一个访问简单Java客户端。...去做: 现在,一些api调用返回丑陋的东西,例如。 resetEnv返回一个可能是JSONArray的Object 。 这是因为不同的环境可能返回不同的结

    app_java_compiler:Android APP,用于编辑和运行Java代码

    online compile(API已经暴露) compile 非常慢 缺点:界面丑陋 no G11n Java编译器 支持写代码,保存,加载文件 图标做的比较漂亮 常用符号快速输入(Tab, {}, ;, \n) 缺点:执行结果是用dialog弹出,不美观 G11n ...

    API-CRUD:API com Knex.js

    带Java脚本SQL查询生成器 回调样式或Promise样式 多种平台(PostgreSQL,MySQL,SQLite3 ...) 敏捷 在所有情况下都有帮助吗? 不,但是您仍然可以编写原始查询 如果不仔细操作,SQL Raw可能很危险,可能很丑陋,...

    phpcr:Java内容存储库(JCR)到PHP的端口

    规范定义了内容存储库(CR)的... 不再学习(数十个)(丑陋的)专有API 编写(主要是)可移植的代码,用于文档管理,Web内容管理,源代码控制比较存储库功能没有更多信息孤岛和供应商锁定以内容为中心的基础架构PHPCR

    java二八杠源码-test:测试

    java二八杠源码格拉菲卡 欢迎来到 Grafika,这是一个 Android 图形和媒体黑客的垃圾场。 涂鸦是: 一系列使用图形功能的黑客。 为 API 18 (Android 4.3) 开发的 SDK 应用程序。 虽然某些代码可能适用于旧版本的 ...

    java二八杠源码-recordgl:记录gl

    java二八杠源码格拉菲卡 欢迎来到 Grafika,这是一个 Android 图形和媒体黑客的垃圾场。 涂鸦是: 一系列使用图形功能的黑客。 为 API 18 (Android 4.3) 开发的 SDK 应用程序。 虽然某些代码可能适用于旧版本的 ...

    java二八杠源码-android---grafika:android---图形

    java二八杠源码格拉菲卡 欢迎来到 Grafika,这是一个 Android 图形和媒体黑客的垃圾场。 涂鸦是: 一系列使用图形功能的黑客。 为 API 18 (Android 4.3) 开发的 SDK 应用程序。 虽然某些代码可能适用于旧版本的 ...

    profique:我当前的 GAE Java 堆栈

    我最喜欢的 Java Google AppEngine Stack,用于基于 REST 的服务器后端。 Objectify - 用于数据访问 Jersey - 用于 REST API,包括文件上传 Guice - DI 将这一切结合在一起 gson - 用于 JSON 序列化 hibernate-...

    java二八杠源码-gles:格莱斯

    java二八杠源码格拉菲卡 欢迎来到 Grafika,这是一个 Android 图形和媒体黑客的垃圾场。 涂鸦是: 一系列使用图形功能的黑客。 为 API 18 (Android 4.3) 开发的 SDK 应用程序。 虽然某些代码可能适用于旧版本的 ...

    java二八杠源码-grafika:图形

    java二八杠源码格拉菲卡 欢迎来到 Grafika,这是一个 Android 图形和媒体黑客的垃圾场。 涂鸦是: 一系列使用图形功能的黑客。 为 API 18 (Android 4.3) 开发的 SDK 应用程序。 虽然某些代码可能适用于旧版本的 ...

    java二八杠源码-VideoHacks:视频黑客

    java二八杠源码视频黑客 欢迎来到 VideoHacks,这是一个 Android 图形和媒体黑客的垃圾场。 VideoHacks 是: 一系列使用图形功能的黑客。 为 API 18 (Android 4.3) 开发的 SDK 应用程序。 虽然某些代码可能适用于旧...

    java二八杠源码-grafikaCamera:图形相机

    java二八杠源码格拉菲卡 欢迎来到 Grafika,这是一个 Android 图形和媒体黑客的垃圾场。 涂鸦是: 一系列使用图形功能的黑客。 为 API 18 (Android 4.3) 开发的 SDK 应用程序。 虽然某些代码可能适用于旧版本的 ...

    java二八杠源码-Grafika-Camera:图形相机

    java二八杠源码格拉菲卡 欢迎来到 Grafika,这是一个 Android 图形和媒体黑客的垃圾场。 涂鸦是: 一系列使用图形功能的黑客。 为 API 18 (Android 4.3) 开发的 SDK 应用程序。 虽然某些代码可能适用于旧版本的 ...

    querydsl-entityql:QueryDSL EntityQL-JPA的本机查询构建器

    使用EntityQL,您可以使用自己的JPA实体和美观,流畅的Java API创建本机查询。 不喜欢JPA注释? 不用担心,EntityQL还支持Spring Data JDBC及其元数据! 想要使用Groovy或Kotlin? EntityQL支持它们,并能够为...

    java二八杠源码-grafika:AndroidStudio上的图形

    java二八杠源码格拉菲卡 欢迎来到 Grafika,这是一个 Android 图形和媒体黑客的垃圾场。 涂鸦是: 一系列使用图形功能的黑客。 为 API 18 (Android 4.3) 开发的 SDK 应用程序。 虽然某些代码可能适用于旧版本的 ...

    java二八杠源码-grafika_vincent:grafika_vincent

    java二八杠源码格拉菲卡 欢迎来到 Grafika,这是一个 Android 图形和媒体黑客的垃圾场。 涂鸦是: 一系列使用图形功能的黑客。 为 API 18 (Android 4.3) 开发的 SDK 应用程序。 虽然某些代码可能适用于旧版本的 ...

    java二八杠源码-android_grafika:android_grafika

    java二八杠源码格拉菲卡 欢迎来到 Grafika,这是一个 Android 图形和媒体黑客的垃圾场。 涂鸦是: 一系列使用图形功能的黑客。 为 API 18 (Android 4.3) 开发的 SDK 应用程序。 虽然某些代码可能适用于旧版本的 ...

    测试数据供应商:扩展TestNG DataProvider

    这很奇怪,因为开发人员倾向于在现代Java世界中使用Stream和Collection API进行数据处理。 如果可以使用以下语法将一些经过过滤和排序的数据提供给测试方法的签名,则只需进行成像即可: @DataSupplierpublic ...

Global site tag (gtag.js) - Google Analytics