美文网首页
Java中常见的坑

Java中常见的坑

作者: IT程序狮 | 来源:发表于2016-07-25 09:32 被阅读421次

译文地址:Java中常见的坑

概述

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

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

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

String s = "Hello";

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

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

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

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

这两个例子中用到了对象池,所以最后引用的是同样的对象。s1==s2a==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的好些个工程师,从他们的反馈感觉,这个问题目前很难解决。

相关文章

  • D13-0729-阿凡提

    D13 D13-0729-阿凡提 如何避开听力训练中的常见坑——Zoe分享 听力训练中的常见坑 听力训练中的常见坑...

  • java常见的坑

    1、对于Integer var=?在-128至127之间的赋值,Integer对象是在IntegerCache.c...

  • java常见的坑

    数值计算BigDecimalBigDecimal核心是精度,精度如果不匹配,结果大概率不会符合预期 初始化设置精度...

  • Java中常见的坑

    译文地址:Java中常见的坑 概述 Java是门极简风格的语言,比其它语言相比,它故意保持较少的特性,不仅在有些不...

  • Java 异常处理

    1. 概述 在本文中, 我们将介绍Java 中异常处理的基础知识,及其一些常见的坑. 2. 前置知识 2.1. 什...

  • Java Concurrency In Practice

    ref: Java Concurrency in Practice 常见线程问题处理 Java thread中对异...

  • Java工程师必须知道的几个关键字

    Java中关键字有54个之多。常用的那些字不必说,有几个关键字并不常见,但是面试中可能成为面试官挖的一个坑,深坑。...

  • 【Java 开发常见的坑】——@Transactional 事务

    Spring中通过@Transactional注解动态代理对目标方法的增强,可以很方便的回滚事务。但是,如果不熟悉...

  • 【Java 开发常见的坑】—— Arrays 使用

    日常开发中,Arrays工具类十分常用,但如果对Arrays的源码不熟悉的话,就有可能踩到坑。以下是我日常开发或身...

  • java基础19-常见坑

    1.使用threadlocal缓存信息,使用之后没有remove,引起数据错乱。因为threadlocal缓存的数...

网友评论

      本文标题:Java中常见的坑

      本文链接:https://www.haomeiwen.com/subject/bcygjttx.html