Day13笔记
一、包装类
1、包装类介绍
含义:基本数据类型对应的类
出现原因:
Java为纯面向对象语言(万物皆对象),而8种基本数据类型不能创建对象,破坏了Java为纯面向对象
语言的特征,所以Java又给这8种基本数据类型分别匹配了对应的类,这种叫做包装里/封装类继承关系:
基本数据类型 | 引用数据类型 |
---|---|
byte | Byte extends Number extends Object |
short | Short extends Number extends Object |
int | Integer extends Number extends Object |
long | Long extends Number extends Object |
float | Float extends Number extends Object |
double | Double extends Number extends Object |
char | Character extends Object |
boolean | Boolean extends Object |
2、 装箱:基本数据类型 -> 包装类
int i = 100;
Integer integer = Integer.valueOf(i);//装箱
System.out.println(integer);
3、 拆箱:包装类 -> 基本数据类型
Integer integer = new Integer(100);
int i = integer.intValue();//拆箱
System.out.println(i);
4、自动装箱:基本数据类型 -> 包装类
int i = 100;
Integer integer = i;//自动装箱(底层实现:Integer.valueOf(i);)
System.out.println(integer);
5、自动拆箱:包装类 -> 基本数据类型
Integer integer = new Integer(100);
int i = integer;//自动拆箱(底层实现:integer.intValue();)
System.out.println(i);
6、注意
注意:
1.数值型都继承Number * 2.int的包装类Integer * 3.char的包装类Character * 4.JDK1.5的新特性:自动装箱、自动拆箱
7、应用场景
应用场景:集合(类似数组的容器),但是集合只能存引用数据类型,如果想存储基本数据类型,就可以把基本数据类型转换为对应的包装类对象
8、案例
需求:把字符串数组{“1”,“2”,“3”,“4”,“5”}转换为int数组。
package com.dream.package_class;
public class Test02 {
public static void main(String[] args) {
/**
* 知识点:包装类
*/
String[] ss = {"1","2","3","4","5"};
int[] is = new int[ss.length];
for (int i = 0; i < is.length; i++) {
//1.将String转换为Integer对象
//2.Integer对象自动拆箱成int数据
int num = Integer.valueOf(ss[i]);
is[i] = num;
}
for (int element : is) {
System.out.println(element);
}
}
}
二、深入包装类底层源码
(一)、 面试题
1、面试题一
判断下列两者是否相同
Integer integer1 = Integer.valueOf(100);
Integer integer2 = Integer.valueOf(100);
System.out.println(integer1 == integer2);//true
Integer integer3 = Integer.valueOf(200);
Integer integer4 = Integer.valueOf(200);
System.out.println(integer3 == integer4);//false
System.out.println(integer1);
System.out.println(integer2);
System.out.println(integer3);
System.out.println(integer4);
System.out.println("-------------");
MyInteger myInteger1 = MyInteger.valueOf(100);
MyInteger myInteger2 = MyInteger.valueOf(100);
System.out.println(myInteger1 == myInteger2);//true
MyInteger myInteger3 = MyInteger.valueOf(200);
MyInteger myInteger4 = MyInteger.valueOf(200);
System.out.println(myInteger3 == myInteger4);//false
System.out.println(myInteger1);
System.out.println(myInteger2);
System.out.println(myInteger3);
System.out.println(myInteger4);
2、面试题深入(Integer底层)
package com.dream.package_class;
public class MyInteger {
private int value;
public MyInteger(int value) {
this.value = value;
}
public static MyInteger valueOf(int i){
if(i >= MyIntegerCache.low && i <= MyIntegerCache.high){
return MyIntegerCache.cache[i - MyIntegerCache.low];
}
return new MyInteger(i);
}
//MyInteger的缓冲类
private static class MyIntegerCache{
private static final int low = -128;
private static final int high = 127;
private static final MyInteger[] cache;
static{
//初始化缓冲数组
cache = new MyInteger[high - low + 1];
int j = low;
for (int i = 0; i < cache.length; i++) {
cache[i] = new MyInteger(j++);
}
}
}
@Override
public String toString() {
return Integer.toString(value);
}
}
3、面试题总结
总结:
Integer底层有个缓存类,缓存类中有个数组,存储了-128~127的Integer对象
Integer.valueOf(num)底层会判断num是否在-128~127这个区间,如果在内就从缓存
数组中获取数据,如果不在这个区间就new对象
三、String类的常用方法
1、案例(String类常用方法)
package com.dream.string_class;
public class Test01 {
public static void main(String[] args) {
/**
* 知识点:String类的常用方法
*/
String str = "123abc";
str = str.concat("DEF123");//在此字符串末尾追加字符串,并返回新的字符串
str = str.substring(2);//从开始下标处截取到字符串末尾,并返回新的字符串
str = str.substring(1, 7);//从开始下标处(包含)截取到结束下标处(不包含),并返回新的字符串
str = str.toUpperCase();//转大写,并返回新的字符串
str = str.toLowerCase();//转小写,并返回新的字符串
str = " 123 a bcD EF 123 ";
str = str.trim();//去除首尾空格,并返回新的字符串
str = str.replace('2', '-');//替换字符,并返回新的字符串
str = str.replaceFirst("3", "林成");//替换第一个出现的字符串,并返回新的字符串
str = str.replaceAll("1", "xxx");//替换字符串,并返回新的字符串
str = str.replaceAll(" ", "");//替换字符串,并返回新的字符串
System.out.println("判断两个字符串内容是否相同:(区分大小写)" + str.equals("xxx-林成abcDEFxxx-3"));
System.out.println("判断两个字符串内容是否相同:(不区分大小写)" + str.equalsIgnoreCase("XXX-林成ABCdefxxx-3"));
System.out.println("判断此字符串是否以某个字符串开头:" + str.startsWith("xxx"));
System.out.println("判断此字符串是否以某个字符串结尾:" + str.endsWith("-3"));
System.out.println("查询此字符串第一次在目标字符串中的下标:" + str.indexOf("-"));
System.out.println("查询此字符串最后一次在目标字符串中的下标:" + str.lastIndexOf("-"));
System.out.println("获取指定下标上的字符:" + str.charAt(4));
//xxx-林成abcDEFxxx-3
System.out.println(str);
//将其他类型转换为字符串
int i = 100;
System.out.println(String.valueOf(i));
boolean bool = true;
System.out.println(String.valueOf(bool));
}
}
2、注意
注意:
String是一个不可变的类, 即一旦一个String对象被创建, 包含在这个对象中的字符序列是不可改变的, 直至该对象被销毁。
3、练习
练习:完成一个邮箱格式的校验 hhy@qq.com
(1),“@”不能在第一位
(2),“.”不能在最后一位
(3),“@”和“.”中间应该有字符
(4),***@***.***
package com.dream.string_class;
public class Test03 {
public static void main(String[] args) {
/**
* 练习:完成一个邮箱格式的校验 hhy@qq.com
(1),“@”不能在第一位
(2),“.”不能在最后一位
(3),“@”和“.”中间应该有字符
(4),***@***.***
*/
String email = "hhy@qq.com";
int index1 = email.indexOf("@");
int index2 = email.indexOf(".");
if(index1 == 0 || index2 == email.length()-1 || (index2-index1)<=1){
System.out.println("邮箱格式错误");
}
}
}
4、深入String创建对象问题
(1)、面试题
面试题1:下列代码创建几个String对象(考点:常量池中的值必须是唯一的)
String str1 = “abc”;
String str2 = “abc”;
答案:一个面试题2:下列代码创建几个String对象(考点:常量池中的值必须是唯一的)
String str1 = new String(“abc”);
String str2 = new String(“abc”);
答案:三个
(2)、常量字符串和变量字符串
package com.dream.string_class;
public class Test05 {
public static void main(String[] args) {
/**
* 知识点:深入String创建对象问题
*/
String str1 = "abc";
String str2 = "abc";
System.out.println(str1 == str2);//true
//两个常量字符串直接在编译时拼接
String str3 = "ab" + "c";
System.out.println(str3 == str1);//true
//两个常量字符串直接在编译时拼接
final String s1 = "ab";
final String s2 = "c";
String str4 = s1+s2;
System.out.println(str4 == str1);//true
//两个变量字符串拼接底层是创建StringBuilder对象
String s3 = "ab";
String s4 = "c";
String str5 = s3+s4;//new StringBuilder(s3).append(s4).toString()
System.out.println(str5 == str1);//false
}
}
四、关于String Buffer、String Builder
一、String Buffer
1、String Buffer介绍
* StringBuffer代表可变的字符序列。 * StringBuffer称为字符串缓冲区, * 它的工作原理是: * 预先申请一块内存,存放字符序列, * 如果字符序列满了,会重新改变缓存区的大小,以容纳更多的字符序列。 * StringBuffer是可变对象,这个是String最大的不同 * * 继承关系:StringBuffer extends AbstractStringBuilder //默认字符串缓冲区:16个字符 StringBuffer sb = new StringBuffer(); //自定义字符串缓冲区:100个字符 StringBuffer sb = new StringBuffer(100); //自定义字符串缓冲区:"123abc".length() + 16 : 22个字符 StringBuffer sb = new StringBuffer("123abc");
2、String Buffer常用方法
package com.dream.stringbuffer_class;
public class Test01 {
public static void main(String[] args) {
sb.append("DEF123");//在末尾追加字符串
sb.insert(6, "xxx");//在指定下标处插入字符串
sb.setCharAt(3, 'A');//替换指定下标上的字符
sb.replace(6, 9, "用良心做教育");//从开始下标处(包含)替换到结束下标处(不包含)的字符串
sb.deleteCharAt(1);//删除指定下标上的字符
sb.delete(5, 11);//从开始下标处(包含)删除到结束下标处(不包含)的字符串
sb.reverse();//反转字符串
//321FEDcbA31
System.out.println(sb);
}
}
二、String Builder
1、String Builder介绍
* StringBuilder代表可变的字符序列。
* StringBuilder称为字符串缓冲区,
* 它的工作原理是:
* 预先申请一块内存,存放字符序列,
* 如果字符序列满了,会重新改变缓存区的大小,以容纳更多的字符序列。
* StringBuilder是可变对象,这个是String最大的不同
*
* 继承关系:StringBuilder extends AbstractStringBuilder
//默认字符串缓冲区:16个字符
StringBuilder sb = new StringBuilder();
//自定义字符串缓冲区:100个字符
StringBuilder sb = new StringBuilder(100);
//自定义字符串缓冲区:"123abc".length() + 16 : 22个字符
StringBuilder sb = new StringBuilder("123abc");
2、String Builder常用方法
package com.dream.stringbuilder_class;
public class Test01 {
public static void main(String[] args) {
/**
* 知识点:StringBuilder
*/
sb.append("DEF123");//在末尾追加字符串
sb.insert(6, "xxx");//在指定下标处插入字符串
sb.setCharAt(3, 'A');//替换指定下标上的字符
sb.replace(6, 9, "用良心做教育");//从开始下标处(包含)替换到结束下标处(不包含)的字符串
sb.deleteCharAt(1);//删除指定下标上的字符
sb.delete(5, 11);//从开始下标处(包含)删除到结束下标处(不包含)的字符串
sb.reverse();//反转字符串
//321FEDcbA31
System.out.println(sb);
}
}
三、两者区别
/**
* StringBuffer vs StringBuilder
*
* 相同点:使用上一模一样,因为他们都继承AbstractStringBuilder
*
* StringBuffer:线程安全的,效率低
* StringBuilder:线程不安全的,效率高
*/
四、字符串频繁拼接问题
经验:频繁的拼接字符串请使用StringBuilder或StringBuffer
package com.dream.stringbuilder_class;
public class Test02 {
public static void main(String[] args) {
/**
* 知识点:字符串频繁拼接问题
*
*/
// //获取自1970.1.1 0:0:0到现在的毫秒数
// long startTime = System.currentTimeMillis();
// String str = "林成";
// for (int i = 0; i < 50000; i++) {
// str += "小可爱,皇冠给你带";
// //str = str + "小可爱,皇冠给你带"
// //str = new StringBuilder(str).append("小可爱,皇冠给你带").toString();
// }
// long endTime = System.currentTimeMillis();
// System.out.println("消耗时长:" + (endTime-startTime));//5746
//获取自1970.1.1 0:0:0到现在的毫秒数
long startTime = System.currentTimeMillis();
StringBuilder sb = new StringBuilder("林成");
for (int i = 0; i < 50000; i++) {
sb.append("小可爱,皇冠给你带");
}
long endTime = System.currentTimeMillis();
System.out.println("消耗时长:" + (endTime-startTime));//5
}
}