当前位置: 首页 > 科技观察

Java常见的陷阱有多少,你没遇到过的有多少?

时间:2023-03-14 19:17:44 科技观察

概述java的陷阱很多,初学者经常会遇到。本文主要包括自动装箱和拆箱。不可变字符串内存泄漏。自增类型使用“==”进行对象比较。双重类型的计算。不可变的StringJavaString类是不可变的(无法修改)。这是因为String对象缓存在String池中。字符串引用的对象可以改变,但字符串对象本身不能改变。字符串是不可变的。一旦创建了字符串,以后就不能更改字符串对象。Java使用按值传递,而不是按引用传递。当你在一个方法中给一个新的值赋值时,它只会修改局部,而不是调用代码中的原始sWrapper类型被转换为原始数据类型。装箱和拆箱的类型是什么?从上图可以看出java的基本类型都可以拆箱。拆箱会发生什么?通过实例,上述两个程序的计算时间相差近10倍。当装箱行为很多时,程序的性能会很低。当封装类型进行==、+、-、*、/计算时,会自动对基础数据类型进行拆箱操作。因此,在执行计算时,使用基本数据类型。Java的核心优势之一是Java垃圾收集器,它管理堆上的对象内存。每当对象变得不可达时,它就会自动释放。然而,对于新手和有经验的程序员来说,一个常见的错误是通过使不再使用的对象可访问来防止内存被释放。这对项目非常不利,因为内存泄漏会阻塞资源并降低应用程序性能。它甚至可能导致java.lang.OutOfMemoryError。常见情况有:静态字段声明。静态字段并在不再需要其数据后忘记将其设置为null不会正常关闭流。Java虚拟机为每个打开的连接分配内存。忘记关闭连接会消耗内存。此类连接可以是:输入流、数据库连接、会话等。finalize()方法。当我们重写finalize()方法时,finalize()只会在对象内存被回收前被调用一次。它有一个不确定的行,只保证方法会被调用,但不保证方法中的任务一定会执行。所以尽量避免使用它。在Java9中,它已被声明为过期函数。Java中使用运算符的自增类型的计算顺序是同一层从左到右计算。查看自增情况。第一种情况的执行上下文如下:1.存储操作数的前一个值。2.增加价值。3、返回之前的值第二种情况的执行上下文如下:1、增加值。2.存储操作数的值(递增)3.返回值使用“==”进行对象比较许多新手程序员尝试使用“==”运算符来比较对象,但当代码的行为并不像意料之中。需要注意的是,关系运算符“==”是在进行引用比较,检查两个对象是否指向内存中的同一位置。使用.equals()方法将消除这个问题,因为它比较对象内部的值。虽然有时“==”运算符会给出预期的答案:原因是什么?同一个字符串用不同的方式创建,为什么差距这么大?Java语言规范中的字符串字面量:同一个包中的不同类里面的字面量字符串表示对同一个String对象的引用。如果还不清楚,再看看这两个字符串的创建过程。当字符串是新的时,第一个新方法做两件事。首先在堆中生成string对象,然后查看常量池中是否有该string。如果有,请忽略它。如果没有,则在常量池中添加第二种类型,直接赋值创建字符串。首先,它会去常量池中查找是否有这样的字符串,如果有就直接指向常量池中的字符串,如果没有就先往常量池中加一个,然后再指向它。以上是两种方法的比较。比较两个整数时,为什么是100就等于200?这是因为Integer使用缓存。在static块中,一次性生成-128到127的直接Integer类型变量,存放在cache[]中。对于-128到127之间的int类型,返回相同的Integer类型对象。整个工作过程是:当Integer.class被加载(Java虚拟机启动)时,其内部类型IntegerCache的静态块开始执行,实例化并暂存取值在-128到127之间的Integer类型对象。当自动装箱的int值在-128到127之间时,直接返回暂存在IntegerCache中的Integer类型对象。Java为什么要这样设计?应该是出于效率的考虑,因为经常会遇到自动装箱,尤其是小值的自动装箱;并且如果每次自动装箱都触发new,在堆中分配内存太耗时了还有其他几个基本类型的包装类,也缓存了Double类型的计算。Java中的double和float在内部表示为二进制小数,因此它们在表示小数时可能不够准确(IEEE标准754)。小数的计算需要精度,需要用到java.math.BigDecimal。Java还是有很多小陷阱的。如果你有,你可以写出来。