Java中常见的坑

概述

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

时间: 2024-10-31 06:35:30

Java中常见的坑的相关文章

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

这篇文章主要介绍了Java中常见的5种WEB服务器介绍,它们分别是Tomcat.Resin.JBoss.WebSphere.WebLogic,需要的朋友可以参考下 Web服务器是运行及发布Web应用的容器,只有将开发的Web项目放置到该容器中,才能使网络中的所有用户通过浏览器进行访问.开发Java Web应用所采用的服务器主要是与JSP/Servlet兼容的Web服务器,比较常用的有Tomcat.Resin.JBoss.WebSphere 和 WebLogic 等,下面将分别进行介绍. Tomc

java中常见的输入输出流案例学习

字节输入流: 1.FileInputStream 用途:从文件系统中的文件获得输入字节,常用于读取图像.声音等原始字节流,读取字符流可考虑使用FileReader 详细构造函数与常用方法可参考API文档,网上已经有中文版的API了,我是个E文盲,伤不起 这里介绍一个最常见的方法: read(byte[] b, int off, int len) 从此输入流中将最多 len 个字节的数据读入一个 byte 数组中. ->off:b字节数组中的偏移量 小知识:数组偏移量,比如a[1,2,3,4,5]

Java中常见的设计模式

我在这里稍微总结一下Java中常见的一些设计模式. 1,单例设计模式 单例设计是Java中最常见的模式之一,,它就是要保证程序里边只有一个对象实例.就好比班上都叫他为班长,是因为得保证班上只有一个班长. 单例设计模式的程序设计思想反应的是Java面向对象思想的封装特性.就是为了保证只有一个对象实例,我们私有化它的构造函数,对外只提供一些相关的 公共方法来获得对象实例. 单例设计模式的实现主要分为饿汉式和懒汉式 饿汉式是先对类的对象实例化,随着类的加载对象也加载进来缺点是会造成性能的损耗好处是实现

Java中常见的jar包的用途

jar包用途  axis.jar   SOAP引擎包  commons-discovery-0.2.jar   用来发现.查找和实现可插入式接口,提供一些一般类实例化.单件的生命周期管理的常用方法.  jaxrpc.jar     Axis运行所需要的组件包  saaj.jar 创建到端点的点到点连接的方法.创建并处理SOAP消息和附件的方法,以及接收和处理SOAP错误的方法.    wsdl4j-1.5.1.jar Axis运行所需要的组件包  activation.jar JAF框架的jar

Java中常见的Exception种类

1.ClassNotFoundException 2.IOException 3.NoSuchFieldException 4.NoSuchMethodException 5.SQLException 6.RuntimeException Java中常见的Exception种类

Java中常见的IO流及其使用

Java中IO流分成两大类,一种是输入流,所有的输入流都直接或间接继承自InputStream抽象类,输入流作为数据的来源,我们可以通过输入流的read方法读取字节数据:另一种是输出流,所有的输出流都直接或间接继承自OutputStream抽象类,输出流接收数据,可以通过write方法写入字节数据.在Java的IO流类中,大部分的输入流和输出流都是成对存在的,即如果存在XXXInputStream,那么就存在XXXOutputStream,反之亦然.(SequenceInputStream和St

java中常见的异常类

1. java.lang.nullpointerexception   这个异常大家肯定都经常遇到,异常的解释是"程序遇上了空指针",简单地说就是调用了未经初始化的对象或者是不存在的对象,这个错误经常出现在创建图片,调用数组这些操作中,比如图片未经初始化,或者图片创建时的路径错误等等.对数组操作中出现空指针,很多情况下是一些刚开始学习编程的朋友常犯的错误,即把数组的初始化和数组元素的初始化混淆起来了.数组的初始化是对数组分配需要的空间,而初始化后的数组,其中的元素并没有实例化,依然是空

java 中常见异常

1. Java.lang.NullPointerException  这个异常大家肯定都经常遇到,异常的解释是"程序遇上了空指针",简单地说就是调用了未经初始化的对象或者是不存在的对象,这个错误经常出现在创建图片,调用数组这些操作中,比如图片未经初始化,或者图片创建时的路径错误等等.对数组操作中出现空指针,很多情况下是一些刚开始学习编程的朋友常犯的错误,即把数组的初始化和数组元素的初始化混淆起来了.数组的初始化是对数组分配需要的空间,而初始化后的数组,其中的元素并没有实例化,依然是空的

java中常见的异常(转)

1. java.lang.nullpointerexception 这个异常大家肯定都经常遇到,异常的解释是"程序遇上了空指针",简单地说就是调用了未经初始化的对象或者是不存在的对象,这个错误经常出现在创建图片,调用数组这些操作中,比如图片未经初始化,或者图片创建时的路径错误等等.对数组操作中出现空指针,很多情况下是一些刚开始学习编程的朋友常犯的错误,即把数组的初始化和数组元素的初始化混淆起来了.数组的初始化是对数组分配需要的空间,而初始化后的数组,其中的元素并没有实例化,依然是空的,