java 中数据类型
基本类型: intshortlongdoublefloatbooleanchar 注意: 并没有 String 的基本类型, 存在于栈中
包装类数据: integerStringDouble 等包装类, 存在于堆
第一个概念:
自动装箱和自动拆箱:
当你用基本类型的值给包装类赋值时, 就会发生基本类型向包装类型的转换: 自动装箱
当你用包装类的值给基本类型的值进行赋值时, 系统也会自动的将包装类转换为基本类型: 自动装箱
第二个实例: Integerdoublefloat 的缓存
Integerdoublefloat 的缓存 cache:
integer: 在 Java 5 中, 为 Integer 的操作引入了一个新的特性, 用来节省内存和提高性能整型对象在内部实现中通过使用相同的对象引用实现了缓存和重用上面的规则适用于整数区间 -128 到 +127,
而且需要注意的是 integer 类型字面量赋值时才会缓存, 而使用构造器创建的 Integer 对象不能被缓存
比如:
Integer abc=new Integer(45); // 不会有缓存这一项操作
其他缓存的对象
这种缓存行为不仅适用于 Integer 对象我们针对所有整数类型的类都有类似的缓存机制
有 ByteCache 用于缓存 Byte 对象
有 ShortCache 用于缓存 Short 对象
有 LongCache 用于缓存 Long 对象
有 CharacterCache 用于缓存 Character 对象
Byte,Short,Long 有固定范围: -128 到 127 对于 Character, 范围是 0 到 127 除了 Integer 可以通过参数改变范围外, 其它的都不行
- System.out.println("自动装箱和自动拆箱");
- Integer a = 1;
- Integer b = 2;
- Integer c = 3;
- Integer d = 3;
- Integer e = 321;
- Integer f = 321;
- Long g = 3L;
- System.out.println(c == d); //true // 缓存
- System.out.println(e == f); //false // 超出缓存的范围
- System.out.println(c.equals(a + b)); //true 第一步进行了自动拆箱, 然后比较两个 int 的值
- System.out.println(c == (a + b)); //true // 算术运算时, 进行自动拆箱, c 变为 int,a+b 变为 int 值, 然后比较两个 int 值
- System.out.println(g == (a + b)); //true // 首先对 a+b 进行自动拆箱为 int, 然后涉及隐式类型转换, int-->long,
- System.out.println(g.equals(a + b)); //false a+b 进行拆箱,
- int A = 1;
- Integer B = 1;
- System.out.println(B.equals(A)); //true
- System.out.println(B == A); //true
String: 是一个特殊的包装类数据
String Str="asd"; 创建 String 类型需要经过三个步骤
1. 首先在常量池中查找是否存在内容为 "abc" 的字符串对象
2. 如果不存在则在常量池中创建一个 "abc" 的字符串对象, 并让 str 引用该对象
3. 如果存在则直接让 str 引用该对象
- String string="asdas";
- String string1="asdas";
- System.out.println(string==string1);\\true
String str = new String("abc")创建实例的过程
1 首先定义一个 str 的 String 类型的引用并存放在栈中
2 在字符串常量池中查看是否存在内容为 "abc" 字符串对象
3 若存在则跳过这个步骤, 若不存在, 则在字符串常量池中创建一个内容为 "abc" 的字符串对象
4 执行 new 操作, 在堆中创建一个指定的对象 "abc", 这里堆的对象是字符串常量池 abc 对象的一个拷贝对象
5 让 str 指向堆中 abc 这个对象(也就是存储这个对象的在堆中的地址)
情景一:
java 虚拟机 (JVM) 中, 存在着一个字符串常量池, 其中保存着很多 String 对象
并且可以被共享使用, 因此它提高了效率, 由于 String 类时 final 的 , 它的值一经创建就不可改变
字符串池由 String 类维护, 我们可以调用 intern()方法来访问字符串池
- String S1="Abc";
- // 字符串创建了一个对象
- String S2="Abc";
- //"Abc" 在字符串池存在, 便生成一个对象 S2 指向 "Abc"
- System.out.println(S1==S2);//true
- System.out.println(""+S1.equals(S2));//true
情景二:
- String S3=new String("Abc");
- // 字符串池生成一个 abc 的对象, 堆中生成一个指向字符串 abc 的对象,
并且生成一个 S3 的引用指向堆中的对象
- String S4=new String("Abc");
- // 字符串池中已经存在 abc, 在堆中生成一个新对象, 生成一个指向堆中对象的引用 S4
- S4==S3 //false 堆中以及字符串池中的地址不相同
情景三; intern()方法可以返回该字符串在常量池中的对象的引用
- String str1 = "abc";
- String str2 = newString("abc").intern();
- System.out.println(str1==str2); //true
情景四: 假改变, 真生成: 看似改变了, 其实时真的生成了
- String str1 = "abc";
- String str2 = "abc";
- str1 = "bcd"; //String 引用改变指向, 指向了 bcd
- // 当 JVM 发现在常量池中没有存放该值的地址, 便开辟这个地址, 并创建了一个对象,
- System.out.println(str1 + "," + str2); //bcd, abc
- System.out.println(str1==str2); //false
情景五: 宏变量宏代替的使用
- String str1 = "abc";
- final String str2 = "ab";
- String str3 = str2+"c";
- System.out.println(str1==str3); // true
- String str1 = "abc";
- String str2 = "ab";
- String str3 = str2+"c";
- System.out.println(str1==str3); // false
涉及到 str2 是变量, str3 不能生成宏代替, 先是生成一个 StringBuilder, 然后 append(str2).append("c")
然后让 str3 指向 StringBuilder.toString()返回的对象
- String S3=new String("Abc");
- // 字符串池生成一个 abc 的对象, 堆中生成一个指向字符串 abc 的对象,
并且生成一个 S3 的引用指向堆中的对象
- String S4=new String("Abc");
- // 字符串池中已经存在 abc, 在堆中生成一个新对象, 生成一个指向堆中对象的引用 S4
- S4==S3 //false 堆中以及字符串池中的地址不相同
来源: http://www.bubuko.com/infodetail-2543388.html