No.5 表达式中的陷阱

1. 关于字符串的陷阱

  • JVM对字符串的处理

    • String java = new String("Java"); 创建了几个对象?

      • 2个。“Java”直接量对应的字符串对象;new String()构造器返回的字符串对象
      • java.intern() 可以字符串池中的直接量对象。
    • 字符串及基本类型的包装类,Java允许通过直接量的方式来创建对应的Java对象;除此之外,简单的算术表达式、连接计算(编译时可以确定具体值)也可以直接创建对应的Java对象
    • 字符串直接量,JVM会使用一个字符串池保存,第一次使用该直接量时,会将其放在字符串池进行缓存(缓存的意思就是以后再用的话,就直接从池中取,而不会新建啦),一般情况下不会对缓存池中的字符串进行垃圾回收
    • 只要是编译时就可以确定其具体值的字符串直接量,JVM会在编译时确定其具体值,并让它指向字符串池中对应的字符串,否则,就不能利用JVM的字符串池了
      • 何为编译时确定具体值?

        • 没有方法调用;没有变量引用
        • 当然,“宏替换”的变量除外
    • String str = "hello" + “world”; 创建了几个字符串对象
      • 1个。因为在编译时就可以确定其计算后的值,因此就直接把计算后的值放到池中就好了,其它的也没有必要啊
    • 在使用字符串、基本类型包装类的对象实例时,尽量通过  直接量 来创建实例。可以少创建一个对象,提升性能。
  • String是典型的不可变类。可变字符串推荐使用StringBuilder
  • 字符串比较
    • 底层是字符串数组
    • 两个字符串左对齐,依次比较二者的每个字符

2. 表达式类型的陷阱

  表达式也是具有制定的数据类型的

  • 表达式类型的自动提升

    • 当算事表达式中含有多个基本数据类型时,整个表达式的数据类型会自动提升,提升到与表达式中最高等级操作数同样的类型。
    • 操作数的等级排列如图示

  • 复合赋值运算符的陷阱(+=、-=、/=、...)

    • E1 op= E2 等价于  E1  = (E1的类型)(E1 op E2)
    • eg:a += 5  等价于 a = (a的类型)(a + 5)
    • 陷阱:它潜在的隐式转换  可能 导致计算结果的   高位“截断”(结果强制转换发生溢出时)
时间: 2024-10-27 06:45:21

No.5 表达式中的陷阱的相关文章

5,表达式中的陷阱

关于字符串的陷阱: 第一次使用某一个字符串直接量得时候,jvm会将它放入字符串池中进行缓存: 关于内存泄漏例子: String str="hello" String str=str+"java" 由于String里包含得字符序列是不能被改变的. 所以第二个str是指向另外一个字符串对象,此时hello字符串就会一次在内存中,垃圾回收机制不会回收它,此时就会内存泄漏. 如果要使用String可变字符串一般使用StringBuffer和StringBuilder,但是S

表达式中的陷阱(分析)

运算符:java中预定义的进行某种特殊运算符号 // + — && <<表达式1.表达式是一种运算符和操作数合成在一 起组成的式子运算符需要的操作数数量不相同,a+b a*b a++ ?:运算符需要的操作数类型别不相同 a+b A+1 1+1 2.表达式都有一个结果 习题: (一). int a = 10: int b = a+(a=5)+a+(a=10); 分析: 10+(a=5)+a+(a=10) a=10 10+5+a+(a=10) a=5 10+5+5+(a=10) a

【JavaScript】JavaScript中的陷阱大集合

本文主要介绍怪异的Javascript,毋庸置疑,它绝对有怪异的一面.当软件开发者开始使用世界上使用最广泛的语言编写代码时,他们会在这个过 程中发现很多有趣的“特性”.即便是老练的Javascript开发者也可以在本文找到一些有趣的新陷阱,请留意这些陷阱,当然也可以尽情享受由这些陷阱 带来的“乐趣”! AD: 本文主要介绍怪异的Javascript,毋庸置疑,它绝对有怪异的一面.当软件开发者开始使用世界上使用最广泛的语言编写代码时,他们会在这个过 程中发现很多有趣的“特性”.即便是老练的Java

编写高质量代码改善C#程序的157个建议——建议38:小心闭包中的陷阱

建议38:小心闭包中的陷阱 先看一下下面的代码,设想一下输出的是什么? static void Main(string[] args) { List<Action> lists = new List<Action>(); for (int i = 0; i < 5; i++) { Action t = () => { Console.WriteLine(i.ToString()); }; lists.Add(t); } foreach (Action t in list

boost在lambda表达式中调用占位符参数的成员函数的方法

boost中提供了lambda表达式的用法,但是lambda表达式的功能还不是很强大,在其中只能对lambda的占位符参数_1等使用最基本的操作符,如+-*/,可是很多时候如果传入的占位符参数是一个对象指针的话,我们可能想要调用这个类的成员函数. 我在开发中遇到了这个问题,需要在stl的算法中传入一个函数来调用对象的比较函数,因为感觉这样太麻烦,还需要重新定义一个函数,所以想起了lambda表达式,c++11的lambda表达式我倒是没试过,可是受项目开发环境所限,只能选择boost.但是我用的

Javascript表达式中连续的 &amp;&amp; 和 || 之赋值区别

function write(msg){ for(var i = 0; i < arguments.length; i ++){ document.write(arguments[i] + '<br />'); } } //关于 '&&' test1 = 1 && 2 && 3 && 4; test2 = '0' && 2 && 3 && 4; test3 = 1 &&

Java随笔:表达式中隐藏的溢出

下面这段代码的输出是什么? long lvar1 = 24 * 60 * 60 * 1000 * 1000; long lvar2 = 24 * 60 * 60 * 1000; System.out.println(lvar1 / lvar2); 一眼看去,应该是1000. 实际的输出是什么呢?5 为什么会得出这样奇怪的结果.我们来反汇编看一下: 执行:javap -c LongOverflowTest.class 结果可以看到: public static void main(java.lan

EL表达式中fn函数

JSTL 使用表达式来简化页面的代码,这对一些标准的方法,例如bean的getter/setter方法,请求参数或者context以及 session中的数据的访问非常方便,但是我们在实际应用中经常需要在页面调用对象的某些方法,例如我需要调用字符串的length方法来获取字符串的 长度时,在以往的开发过程中我们必须把对象先转为String类,然后在调用其length方法,这样的代码繁琐而且容易出错. 因此JSTL内置了几个用于字符串操作的方法,可以直接在表达式中使用,大大的简化了代码,提供代码的

12.3.3.1 序列表达式中的平面映射

假设我们有一个关于城市的元组列表,每个元组包含城市的名字和它所在的国家,另外,我们还有一个列表,是用户所选的城市.因此,我们可以这样表示样本数据: let cities = [ ("New York","USA"); ("London", "UK"); ("Cambridge","UK"); ("Cambridge", "USA") ] let e