1. 求长度各有千秋

你是否曾经在面试的时候,经常被问到:数组有没有 length() 方法?字符串有没有 length() 方法? 集合有没有 length() 方法?

面对这个问题,那么不得不吐槽一下,Java 中获取长度的方式,设计着实有点乱,对刚入门的程序猿而言,那绝对是一脸的懵逼。

String[] array = {"abc", "def"};
String str = "abcedf";
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("def");
System.out.println("数组的长度: " + array.length);
System.out.println("字符串的长度: " + str.length());
System.out.println("集合的长度: " + list.size());

正式科普一下,希望能够铭记你心中。数组求长度用 length 属性;字符串求长度用 length() 方法;集合求长度用 size() 方法。

2. 字符串截取有深意

对于程序猿来说,编程规范能够养成良好的编程习惯,提高代码质量,减少沟通成本。阿里 Java 开发手册编程规约中记载,【强制】方法名、參数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从驼峰形式。

看到这里,不得不提 String 中的 substring 方法,你是不是经常把“substring”写成“subString”。本次这个命名不是吐槽的重点。主要想分享如下代码片段。

public class StringInterview {
   public static void main(String[] args) {
       String str = "......abcdefgh.......";
       String subStr = str.substring(1,3);
       str = null;
       System.out.println(subStr);
   }
}

假如上述这段程序在 Java 1.6 中运行,代码中虽然强制使 str 引用为空,本意是释放 str 占用的空间,但是这个时候,GC 是无法回收这个大的 char 数组的,因为还在被 subStr 字符串内部引用着,虽然 subStr 只截取这个大数组的一小部分。当 str 是一个非常大字符串的时候,这种浪费是非常明显的,甚至会带来内存泄露问题。

深入 Java 1.6 中 substring 的设计一探究竟。

public String substring(int beginIndex, int endIndex) {
  if (beginIndex < 0) {
      。。 。。 。。
  }
  if (endIndex > count) {
       。。 。。 。。
  }
  if (beginIndex > endIndex) {
       。。 。。 。。
  }
  return ((beginIndex == 0) && (endIndex == count)) ? this :
   new String(offset + beginIndex, endIndex - beginIndex, value);
}

到此你应该拨云见日豁然开朗。当我们调用字符串 str 的 substring 得到字符串 subStr,其实这个操作,无非就是调整了一下 subStr 的 offset 和 count ,用到的内容还是 str 之前的 value 字符数组,并没有重新创建新的专属于 subStr 的内容字符数组。如果 subStr 的生命周期要长于 str 或者手动设置 str 为null,当垃圾回收进行后,str 被回收掉,subStr 没有回收掉,那么内存占用依旧存在,因为 subStr 持有 str 字符数组的引用。

正式科普一下,这个问题出现在 Java 1.6,并且 Java 1.7 中已经修复。虽然已经修复,并不代表我们就不需要了解,如果你正在求职路上,稍微了解一下,说不定会加分。

3. 一条 if 语句引发不满

先给各位抛一段 Java LinkedList 类的代码片段,一起吐槽吐槽。

public E getFirst() {
   final Node<E> f = first;
  if (f == null)
       throw new NoSuchElementException();
   return f.item;
}

JDK 中 if 语句后只有一条语句,大部分都是这么实现的。原则上,if 语句如果后面跟着只有一句话,是可以不加的。但是在我们实际开发中,有些现象却会让你匪夷所思,不信你看看下面的代码片段。
片段一:

if (f == null)
   //抛出异常,或者加一条打印语句,加上此句注释逻辑就变了
   throw new NoSuchElementException();

片段二:

public class Interview {
   public static void main(String[] args) {
       Class c = Interview.class;
       try {
           Object o = c.newInstance();
           if (o instanceof Interview)
               Interview tt = (Interview) o; //为什么会报错?请各位解释原因
       } catch (Exception e) {
           e.printStackTrace();
       }
   }
}

正式科普一下,看似一个简单的编码规范,背后隐藏了多少坑啊,所以为了良好的编程习惯,建议还是统一加上大括号为好,良好的编码习惯是真重要啊。

4. 时间实现也找茬

Tiago Fernandez 做过一次投票,选举最烂的 Java API,排第二的就是日期 API(Date 和Calender)。一言不合就抛代码,如下片段是计算两个日期之间的天数。

public static void main(String[] args) {
   Calendar begin = Calendar.getInstance();
   begin.set(1990, Calendar.JUNE, 17);
   Calendar end = Calendar.getInstance();
   System.out.println(alculatedDays(begin, end));
   System.out.println(alculatedDays(begin, end)); // 为什么显示 0?
}
public static long alculatedDays(Calendar begin, Calendar end) {
   long days = 0;
   while (begin.before(end)) {
       begin.add(Calendar.DAY_OF_MONTH, 1);
       days++;
   }
   return days;
}

alculatedDays 方法,如果连续计算两个 Date 实例的话,第二次会取得 0,因为 Calendar 状态是可变的,考虑到重复计算的场合,最好复制一个新的 Calendar,改造如下

public static long alculatedDays(Calendar begin, Calendar end) {
   Calendar calendar = (Calendar) begin.clone(); // 复制
   long days = 0;
   while (calendar.before(end)) {
       calendar.add(Calendar.DAY_OF_MONTH, 1);
       days++;
   }
   return days;
}

不过万物都在向前进化,因为由于原来老旧的日期 API 一直被人诟病,所以 JDK 1.8 中对日期的改动是特别大的,基本上是引入了一套全新易用的 API,各位有时间可以体验一下。

好了,吐槽中见真谛,今天就讲这么多吧。希望你能 get 到一点点共鸣,如果你比较感兴趣,就多多关注和分享给身边的朋友吧。

吐槽:那些Java设计中不得不说的槽点的更多相关文章

  1. 吐槽,Java 设计的槽点

    今天不灌水,直接上干货!希望下面的讲解,能与你产生一些共鸣. 1. 求长度各有千秋 你是否曾经在面试的时候,经常被问到:数组有没有 length() 方法?字符串有没有 length() 方法? 集合 ...

  2. Java的GUI设计中如何跨界面传值

    在Java设计中我们会遇到登录界面的信息,在后面的某个情况也需要使用. 比如这是笔者的一个登录界面 可以看到获取密码和账号 在这个时候的功能的完成需要密码和账号 // 登录信息的获取 public S ...

  3. 在Java API设计中,面向接口编程的思想,以及接口和工厂的关系

    现在的java API的设计中,提倡面向接口的编程,即在API的设计中,参数的传递和返回建议使用接口,而不是具体的实现类,如一个方法的输入参数类型应该使用Map接口,而不是HashMap或Hashta ...

  4. Java Map 集合类在selenium自动化测试设计中的应用

    我们在设计自动化测试用例的时候,往往很多工作是在处理测试的数据. 测试数据无论用Excel 文件, XML文件或者任何一种形式测存储方式,都会设计到参数化以及我们对数据的操作. 这个时候,我们会用到以 ...

  5. 【Java心得总结六】Java容器中——Collection

    在[Java心得总结五]Java容器上——容器初探这篇博文中,我对Java容器类库从一个整体的偏向于宏观的角度初步认识了Java容器类库.而在这篇博文中,我想着重对容器类库中的Collection容器 ...

  6. Java编程中“为了性能”尽量要做到的一些地方

    最近的机器内存又爆满了,除了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过于随意化,这些不好的习惯或对程序语言的不了解是应该好好打压打压了. 下面是参考网络资源总结的一些在Ja ...

  7. 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)

    编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...

  8. java编程中'为了性能'一些尽量做到的地方

    原文地址:http://blog.csdn.NET/m13666368773/article/details/7796924 最近的机器内存又爆满了,出了新增机器内存外,还应该好好review一下我们 ...

  9. Java开发中的23种设计模式详解

    [放弃了原文访问者模式的Demo,自己写了一个新使用场景的Demo,加上了自己的理解] [源码地址:https://github.com/leon66666/DesignPattern] 一.设计模式 ...

随机推荐

  1. OpenGL(十二) 纹理映射(贴图)

    OpenGL绘制纹理的步骤: 1. 开启纹理功能 使用glEnable(GL_TEXTURE_2D)开启2D纹理功能,使用glDisable(GL_TEXTURE_2D)关闭纹理,默认情况下纹理是关闭 ...

  2. HQL链接查询

    和SQL查询一样,HQL也支持各种各样的连接查询,如内连接.外连接.我们知道在SQL中可通过join字句实现多表之间的连接查询.HQL同样提供了连接查询机制,还允许显示指定迫切内连接和迫切左外连接.H ...

  3. 【转载】json 数据 添加 删除 排序

    张映 发表于 2014-02-10 分类目录: js/jquery 标签:json, 删除, 排序, 添加 js数据格式和json数据格式,各有各的用处,就个人而言,json更好用一点,js自身的数组 ...

  4. Linux杂谈: 树形显示多级目录--tree

    最近写博客的时候偶尔会需要将文件目录结构直观地列出来,例如python的包结构. 于是在网上搜了搜,发现了一个Linux下还不错的工具--tree tree 可以很直观地显示多级目录结构. 1. 安装 ...

  5. 使用IntelliJ IDEA开发SpringMVC网站(三)数据库配置

    原文:使用IntelliJ IDEA开发SpringMVC网站(三)数据库配置 摘要 讲解在IntelliJ IDEA中,如何进行Mysql数据库的配置 目录[-] 文章已针对IDEA 15做了一定的 ...

  6. jquery.tmpl.js使用外部 jQuery Template文件

    $.get('/js/templates/filename.html', function(template) { $.tmpl(template, data).appendTo('#whatever ...

  7. ArcGIS 10.3 for Server 在windows下的安装教程

    原文:ArcGIS 10.3 for Server 在windows下的安装教程 以下是10.2的教程,10.3同样适用. 许可文件: ArcGIS For Server10.3许可文件 - 下载频道 ...

  8. API HOOK介绍 【转】

    什么是“跨进程 API Hook”? 众所周知Windows应用程序的各种系统功能是通过调用API函数来实现.API Hook就是给系统的API附加上一段小程序,它能监视甚至控制应用程序对API函数的 ...

  9. PostgreSQL在win7上安装详细步骤

    原文:PostgreSQL在win7上安装详细步骤 PostgreSQL安装: 一.windows下安装过程 安装介质:postgresql-9.1.3-1-windows.exe(46M),安装过程 ...

  10. 命令行程序如何获取HINSTANCE?

    main() { HINSTANCE hinst = GetModuleHandle(NULL); }