Day23
P17 装箱和拆箱
把栈中的基本类型 转换 成堆中的对象,叫装箱
把堆中的数据 转换到 栈里面,叫拆箱
- 装箱:把基本类型转换成引用类型;
拆箱:把引用类型转换成基本类型; - API文档
package com.changyonglei.baozhuanglei.demo01;
public class Demo01 {
public static void main(String[] args) {
int num=10;
//分手动装拆箱 和 自动装拆箱
//以下为JDK1.5之前装箱拆箱的方法
//类型转换:装箱,基本类型转成引用类型的过程
//基本类型
int num1=18;
//使用Integer包装类创建对象
Integer integer1=new Integer(num1);//第一种装箱方式:利用构造方法
Integer integer2=Integer.valueOf(num1);//第二种装箱方式:用valueOf
System.out.println("装箱");
System.out.println(integer1);
System.out.println(integer2);
//类型转换:拆箱,引用类型转成基本类型
Integer integer3=new Integer(100);
//创建了一个引用类型,integer3在堆里放,堆里有一个属性100
//引用类型转换为基本类型:
int num2=integer3.intValue();
System.out.println("拆箱");
System.out.println(num2);
//以上为JDK1.5之前装箱拆箱的方法
//JDK1.5之后,有提供自动装箱和拆箱
int age=30;
//自动装箱 基本类型转成引用类型的过程
Integer integer4=age;
System.out.println("自动装箱");
System.out.println(integer4);
//自动拆箱 引用类型转成基本类型
int age2=integer4;
System.out.println("自动拆箱");
System.out.println(age2);
//自动装拆箱是直接把基本数据赋给引用类型 或者直接把引用类型赋给基本类型
//其实软件内部自动还是用的之前手动装拆箱的方式,只不过没有直接显示
}
}
/*
输出: 装箱
18
18
拆箱
100
自动装箱
30
自动拆箱
30
*/
P18 基本类型和字符串转换
8种包装类提供不用类型间的转换方式
-
Number父类中提供的6个共性方法
-
parseXXX()静态方法 :把字符串转成基本类型 ,XXX表示一种变量类型,int double 等等类型
-
valueOf( )静态方法 :把基本类型转成引用类型
-
注意:需保证类型兼容,否则抛出NumberFormatException异常
package com.changyonglei.baozhuanglei.demo01;
public class Demo01 {
public static void main(String[] args) {
int num=10;
//基本类型和字符串之间转换
//1.基本类型转成字符串
int n1=100;
int n0=15;
//1.1 方法1:使用+号
String s1=n1+"";
//1.2 方法2:使用Integer中的toString方法
String s2=Integer.toString(n1);
String s0=Integer.toString(n0,16);
//这里用了toString第二种方法toString(int i,int radix)
//这里的radix表示转换成几进制的数,填16表示转换成16进制
System.out.println(s1);//输出100
System.out.println(s2);//输出100
System.out.println(s0);//输出f 因为15用16进制表示是f
//2.字符串转成基本类型
String str="150";
//2.1 方法1:使用Integer.parseXXX();方法
int n2 = Integer.parseInt(str);
System.out.println(n2);//输出150
//3.boolean字符串形式转成基本类型,"true"-->true 非“true”-->false
String str2="true";
String str0="fsdgj";
boolean b1=Boolean.parseBoolean(str2);
boolean b0=Boolean.parseBoolean(str0);
//Boolean是boolean类型的包装类
System.out.println(b1);//输出true
System.out.println(b0);//输出false
//注意:需保证类型兼容,否则抛出NumberFormatException异常
}
}
P19 Integer缓冲区
整数缓冲区
-
Java预先创建了256个常用的整数包装类型对象
-
在实际应用当中,对已创建的对象进行复用
package com.changyonglei.baozhuanglei.demo01;
public class Demo02 {
public static void main(String[] args) {
//面试题
Integer integer1=new Integer(100);
//把基本类型100转换成引用类型integer1和2
Integer integer2=new Integer(100);
System.out.println(integer1==integer2);//输出false
//问题:为什么输出false?integer1和2不都是100吗?
/*回答:integer1和integer2是引用类型,引用类型数据在 堆 里存放,
integer1变量和integer2变量在 栈 里面,他们指向了在堆里的两
个对象,==比的是栈里integer1变量和integer2变量里面存的地址,
显而易见两个地址不一样,所以==比出来结果是false
*/
// Integer integer3=Integer.valueOf(100);//自动装箱内部用的valueOf方法
// Integer integer4=Integer.valueOf(100);//自动装箱内部用的valueOf方法
// System.out.println(integer3==integer4);//输出true
//
// Integer integer5=Integer.valueOf(200);//自动装箱内部用的valueOf方法
// Integer integer6=Integer.valueOf(200);//自动装箱内部用的valueOf方法
// System.out.println(integer5==integer6);//输出false
//上边一块是下边一块自动装箱时软件内部运作时用的Integer.valueOf()方法
//上边一块是下边一块实际是一样的
Integer integer3=100;//自动装箱
Integer integer4=100;//自动装箱:把基本类型转成引用类型
System.out.println(integer3==integer4);//输出true
Integer integer5=200;//自动装箱
Integer integer6=200;
System.out.println(integer5==integer6);//输出false
//问题:为什么(integer3==integer4)是true,(integer5==integer6)是false?
/*回答:堆空间 里有一个integer数组,这个数组保存了从 -128到128 之间的这些对象都给
创建好了,这个地方就叫做Integer缓冲区,如果我们给integer赋值100的话,
Integer.valueOf()方法它就会去Integer缓冲区找一找,看有没有100这个对象,
如果有的话就把这个对象给 栈 里面的这个变量integer3(或integer4或等等其他变量)
所以变量integer3和integer4指向 堆 里面的对象是Integer缓存区里面的100这个
对象,这俩变量指向的是同一个对象,所以栈里的integer3变量里存的地址和integer4变量
里存的地址一样,又因为==比较的是变量integer3和integer4里面存的地址,所以
(integer3==integer4)输出结果为true
第二次我们给Integer integer5和integer6赋值200,因为Integer缓冲区对象范围
为-128到127之间,200不在这个范围,Integer.valueOf()方法内部就 new Integer(i),
就直接在 堆 里面开辟了一个空间存200这个对象,integer5和integer6两次共在堆里开辟了
(new了)两块空间放两个对象200,这两块空间地址不一样,又因为==比较的是变量integer5和
integer6里面存的地址,所以(integer5==integer6)的输出结果为 false
*/
}
}
P20 String概述
String类
- 字符串是常量,创建之后不可改变
- 字符串字面值存储在字符串池中,可以共享
- String s = “Hello”;产生一个对象,字符串池中存储
- String s = new String(“Hello”); 产生两个对象,堆、池各一个
package com.changyonglei.baozhuanglei.demo01;
public class Demo03 {
public static void main(String[] args) {
String name="hello";
/*这个“hello”常量存储在字符串池中,字符串池
里开辟空间存hello,name变量在栈里,里面存地址,指向
字符串池里的hello
*/
name="zhangsan";
/*"zhangsan"赋值给name变量,给字符串变量name赋值时,
并没有修改或改动字符串池里的”hello“,而是重新开辟一个空间
存放“zhangsan”,此时name里的地址指向字符串池里的“zhangsan”,
而不指向“hello”了,hello此时没被改变,就反映了(字符串是常量,
创建之后不可改变)这句话,hello此时变成垃圾,当触发垃圾回收器的时
候hello就被回收了,
如下图
*/
}
}
String name2="zhangsan";
/* 把“zhangsan”赋值给name2
此时程序会去字符串池里找一下是否有“zhangsan”这个字符串,
如果有,那么就把这个字符串“zhangsan”赋给name2,那么栈里
的name2也指向(和name变量一样)常量池里已存在的“zhangsan”,
此时name里地址改变,name和name2里面存的地址变成一样的了
体现了(字符串字面值存储在字符串池中,可以共享)这句话
如下图
*/
//演示字符串的另一种创建方式,即:
//String s = new String("Hello"); 产生两个对象,堆、池各一个
String str=new String("java");
/*
此时栈里开辟变量str,此时程序先去字符串池里找是否有“java”,没有找到
的话就在常量池里创建一个 对象,这个对象里面存的“java”,
然后程序再调用 new String调用构造方法,这时候就在 堆 里创建了一个对象
保存的是“java”,这时候 栈 里面的str存的地址指向了 堆 里的对象“java”,
这时候程序里就出现两个对象,栈里的str存的是堆里“java”的地址而不是常
量池的“java”地址
如下图
*/
程序实际运行时只有一个“java”,堆中没有“java”,但有一个对象,加上常量池的此时共有
2个对象,先做了解,如图:
String str=new String("java");
String str2=new String("java");
System.out.println(str==str2);//输出false
//问题:(str==str2)为什么是false?
/*回答:因为str2的时候,new String 在 堆 里创建了一个对象存放“java”,
此时str2里的地址指向的是堆里新建的这个对象的地址,而不是常量池
里“java”的地址,所以str和str2里的地址不一样,所以
(str==str2)输出false
如下图
*/
String str=new String("java");
String str2=new String("java");
System.out.println(str==str2);//输出false
System.out.println(str.equals(str2));//输出true
//问题:(str.equals(str2));为什么是true?
/*回答:因为.equals比的是数据,而不是地址,因为“true”和“true”数据一样,
所以System.out.println(str.equals(str2))输出为true
*/