概述

Java是门极简风格的语言,比其它语言相比,它故意保持较少的特性,不仅在有些不常见的情况下会出些奇奇怪怪的错误,即使很一般的情况下也有可能让人栽根头。如果你习惯了别的语言,你读Java 的代码很容易搞错一些概念。

变量要么是引用 ,要么是基础类型

这是对的,变量不是对象。也就是说在下面这个例子里,s不是个对象,也不是字符串,它只是一个字符串的引用。

String s = "Hello";

这个能解释很多的问题,比如: 问题:如果说字符 串是不可变的,为什么我能修改它? s+=“!” 回答:在Java里是不可变的,你改变的只是引用而已。

==比较的是引用,不是内容

让人更混乱的是,有时候用==是能比较内容的。如果你有两个一样的不可变值,JVM会尝试引用 同一个对象 。

String s1 = "Hi", s2 = "Hi";
Integer a = 12, b = 12;

这两个例子中用到了对象池,所以最后引用 的是同样的对象。s1==s2和a==b都是返回true,JVM已经把两个引用 都指向了同一个对象。然而,如果稍微改下代码,JVM没有把对象放到池里的话,==就会返回false,可能会让你意想不到。这个时候你得用equals了。

String s3 = new String(s1);
Integer c = -222, d = -222;
s1 == s2 // is true
s1 == s3 // is false
s1.equals(s3) // is true
a == b // is true
c == d // is false (different objects were created)
c.equals(d) // is true

对于整型来说,对象池缓存的范围是-128到127(还有可能更高)。

Java通过传值进行引用传递

所有的变量都是传值,包括引用。这就是说如果你有个变量,它是一个对象的引用,这个引用会被拷贝后再传参,而不是传递的对应的那个对象。

public static void addAWord(StringBuilder sb) {
sb.append(" word");
sb = null;
} StringBuilder sb = new StringBuilder("first ");
addWord(sb);
addWord(sb);
System.out.println(sb); // prints "first word word"

引用的对象可以改变,不过如果修改拷贝的这个引用,对调用方是没有影响的。

在大多数JVM实现里,Object.hashCode和内存地址无关

hashCode必须是保持不变的。不然的话HashSet或者ConcurrentHashMap就没法玩了。然而对象可以在内存的任何地方,并且它的位置还可能不断变化,而这个对你的程序来说是透明的。使用内存地址来当做hashCode是不可行的(除非你自己有一个JVM,对象是固定不动的)。 对于 OpenJDK和Hotspot JVM来说,hashCode是按需生成的,并存储在对象的头部。使用Unsafe API你看到hashCode是否已经生成了,甚至还可以修改它。

Object.toString那些不为人知的事情

toString的默认行为是打印类的的内部名称还有对象的hashCode。 上面已经提到,hashCode并不是内存地址,尽管它是用16进制打印的。同样的,类名,尤其是数组的类名,更容易让人头晕。比如说String[]的名称是[Ljava.lang.String; 这个[表明它是个数组,L说明它是Java语言(Language)创建的类,并不是基础类型比如byte这些,顺便提一下byte内部名称是B。;号标识类的结束。比如你有个这样的数组:

String[] words = { “Hello”, “World” };
System.out.println(words);

输出会是这样:

[Ljava.lang.String;@45ee12a7

很不幸你只知道这是个对象数组。如果你只有一个Object实例words,这样是不够的,你得调用下Arrays.toString(words)。这极其恶劣地破坏了封装的原则,在StackOverflow上面这也是最常见的一类问题。

我问过Oracle的好些个工程师,从他们的反馈感觉,这个问题目前很难解决。

原创文章转载请注明出处:http://it.deepinmind.com/java/2014/03/07/Java-common-problems.html

Java中常见的坑的更多相关文章

  1. Java中常见的5种WEB服务器介绍

    这篇文章主要介绍了Java中常见的5种WEB服务器介绍,它们分别是Tomcat.Resin.JBoss.WebSphere.WebLogic,需要的朋友可以参考下 Web服务器是运行及发布Web应用的 ...

  2. Java中常见的Exception种类

    Java中常见的Exception种类 1.ClassNotFoundException 2.IOException 3.NoSuchFieldException 4.NoSuchMethodExce ...

  3. Java基础-JAVA中常见的数据结构介绍

    Java基础-JAVA中常见的数据结构介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是数据结构 答:数据结构是指数据存储的组织方式.大致上分为线性表.栈(Stack) ...

  4. Java中常见的注解

    Java中常见的注解 1.JDK自带的注解@Override  @Deprecated  @Suppvisewarnings 常见第三方注解 Spring:@Autowired  @Service  ...

  5. Java中常见的异常类型

    一. Java中常见的异常类 异常类 说明 ClassCastException 类型准换异常 ClassNotFoundException 未找到相应类异常 ArithmeticException ...

  6. Java 中常见的 final 类

    Java 中常见的 final 类 java.lang 包 public final class Boolean extends Object implements Serializable, Com ...

  7. java中常见的六种线程池详解

    之前我们介绍了线程池的四种拒绝策略,了解了线程池参数的含义,那么今天我们来聊聊Java 中常见的几种线程池,以及在jdk7 加入的 ForkJoin 新型线程池 首先我们列出Java 中的六种线程池如 ...

  8. java中的那些坑

    最近准备换工作,为了少让人家鄙视,就要狠狠地藐视这些面试题目.找了本电子书,发了有好多坑,都是特别简单,但是很少有人做对的题目.面对这样的题目,我却有一种兴奋的感觉,也许是因为一直做着重复的工作没有新 ...

  9. java 中常见异常

    1. Java.lang.NullPointerException  这个异常大家肯定都经常遇到,异常的解释是"程序遇上了空指针",简单地说就是调用了未经初始化的对象或者是不存在的 ...

随机推荐

  1. cat的用法总结

    1 查看文件在LINUX下一切皆文件,光看见文件名和目录名对我们来说,还远远不够.今天,就来介绍一下可以打开文件的命令cat.当然,二进制的可执行文件,不能用cat. 在CentOS7下,以/etc/ ...

  2. python3 + selenium + eclipse 中报错:'chromedriver' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home

    解决:提示chrome driver没有放置在正确的路径下,于是下载chrome dirver,然后放置到C:\Python36的目录下,再次运行就OK了!

  3. Logstash-安装logstash-filter-multiline插件(解决logstash匹配多行日志)

    ELK-logstash在搬运日志的时候会出现多行日志,普通的搬运会造成保存到ES中日志一条一条的保存,很丑,而且不方便读取,logstash-filter-multiline可以解决该问题. 接下来 ...

  4. c#正则表达式替换

    替换规则: 替换中包含原部分逐句,可以用分组的方式来替换,用?<组名>来标记需要记录的数据,在替换的时候使用 ${组名} 或者 <组名> 来加载这部分数据. 例如: 替换:&l ...

  5. In-App Purchase Configuration Guide for iTunes Connect---(一)----Introduction

    Introduction In-App Purchase is an Apple technology that allows your users to purchase content and s ...

  6. 使用API修改控制台输出的颜色(前景色和背景色)

    1.api原型 SetConsoleTextAttribute BOOL WINAPI SetConsoleTextAttribute( _In_ HANDLE hConsoleOutput, // ...

  7. 1.14不使用回车键来读取n个字符

    read是一个重要的bash命令,它用于从键盘或标准输入中读取文本.可以使用read以交互的形式读取来自用户的输入,不过read能做的远不止这些.很多编程语言的输入库都是从键盘读取输入,且只有回车键按 ...

  8. The Truth About GCHandles

    I've heard several people asking why GCHandle doesn't implement IDisposable, considering it wraps an ...

  9. Python包管理工具小结

    此文已由作者张耕源授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 作为一名接触Python有一段时间的初学者,越来越体会到Python的方便之处,它使人能更 多的关注业务本身 ...

  10. ue4 创建简易动画

    这个功能本来是在原动画基础上做调整用的,所以直接用来做动画并不是很合适,如果要做复杂动画,叠加的轨迹会非常多,不好用 (蒙皮好的)模型右键,创建一个动画合成 点开这个动画合成,创建动画序列(就是普通动 ...