文章目录
一、包装类
-
包装类:基本数据类型对应的引用数据类型
-
出现原因:Java为纯面向对象语言,但是8种基本数据类型不能new对象,破坏了Java为纯面向对象语言的特征所以Java为每种基本数据类型匹配了对应的类,这种类叫做包装类/封装类
-
包装类的层次结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3pupRnTI-1611308097043)(file:///C:/Users/刘效廷/AppData/Local/Temp/msohtmlclip1/01/clip_image002.png)]
-
包装类中的常用方法
装箱:把基本数据类型包装为对应的包装类对象 10
Integer i1 = new Integer(10); // 利用构造方法
Integer i2 = Integer.valueOf(10); //利用包装类中的静态方法
**拆箱:**把包装类对象转换为对应的基本数据类型。
int i3= i1.intValue(); //返回包装类对象i1对应的基本数据
-
自动装箱和自动拆箱
前面的装箱和拆箱操作,相对较麻烦。自jdk1.5开始,java增加的对基本数据类型的自动装箱和自动拆箱操作。
java编译器在编译时期会根据源代码的语法来决定是否进行装箱或拆箱。
1、 自动装箱:可以直接把一个基本数据类型赋值给包装类
例如: Integer i1 = 10; //自动装箱操作
2、 自动拆箱:可以直接把一个包装类对象,赋值给基本类型
例如:int a = new Integer(3); //自动拆箱。
自动装箱和自动拆箱,简化了对包装类的操作。
注意:需要理解自动装箱和拆箱的本质
-
基本数据类型 引用数据类型
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
-
//装箱:把基本数据类型 转换为 对应的包装类对象
Integer integer = Integer.valueOf(10);
System.out.println(integer);
//拆箱:把包装类的对象 转换为 对应的基本数据类型
int i = integer.intValue();
System.out.println(i);
//自动装箱:把基本数据类型 转换为 对应的包装类对象
Integer integer = 10;
System.out.println(integer);
//自动拆箱:把包装类的对象 转换为 对应的基本数据类型
int i = integer;
System.out.println(i);
注意:自动拆装箱是JDK1.5开始的新特性
需求:把该字符串数组转换为int数组
String[] ss = {"1","2","3","4","5","6"};
int[] is = new int[ss.length];
for (int i = 0; i < ss.length; i++) {
//获取出单个的字符串
String str = ss[i];
//转换为int类型
int num = Integer.parseInt(str);
//赋值
is[i] = num;
}
for (int e : is) {
System.out.println(e);
}
经典面试题
二、字符串
String创建对象问题
常量池概念:
Java运行时会维护一个常量池, 常量池用来存放运行时中产生的各种字符串,并且池中的字符串的内容不重复。
//"abc"常量池中只有一份
//有1个String的对象
String str1 = "abc";
String str2 = "abc";
System.out.println(str1 == str2);//true
//new了两次,“abc”在常量池中
//有3个String的对象
String str3 = new String("abc");
String str4 = new String("abc");
System.out.println(str3 == str4);//false
String str1 = "abc";
String str2 = "abc";
System.out.println(str1 == str2);//true
//"ab"字面值常量
//"c"字面值常量
//在编译时,就直接拼接为"abc"
String str3 = "ab" + "c";
System.out.println(str1 == str3);//true
//s1 常量
//s2 常量
//在编译时,就直接拼接为"abc"
final String s1 = "ab";
final String s2 = "c";
String str4 = s1 + s2;
System.out.println(str1 == str4);//true
//s3 和 s4 中有一个是常量 或者 都是变量的情况下
final String s3 = "ab";
String s4 = "c";
String str5 = s3 + s4;//new StringBuilder(s3).append(s4).toString();
System.out.println(str1 == str5);
总结:
两个常量字符串拼接,在编译时就直接拼接
其中有一个是变量的情况,底层会创建一个StringBuilder的容器进行存储
String类的常用方法
String str = "123abcDEF";
str = str.concat("123");//在字符串末尾追加内容,并返回新的字符串
str = str.substring(2);//从开始下标处截取到字符串末尾,并返回新的字符串
str = str.substring(1, 7);//从开始下标处(包含)截取到结束下标处(不包含),并返回新的字符串
str = str.toLowerCase();//转小写,并返回新的字符串
str = str.toUpperCase();//转大写,并返回新的字符串
str = " 123 abc DEF 1 2 3 ";
str = str.trim();//去掉首尾空格,并返回新的字符串
str = str.replace('2', '-');//替换字符,并返回新的字符串
str = str.replaceAll(" ", "");//替换字符串,并返回新的字符串
str = str.replaceFirst("3", "888");//替换第一个出现的字符串,并返回新的字符串
System.out.println("获取字符串字符的个数:" + str.length());
System.out.println("比较两个字符串内存地址是否相等:" + (str == "abc"));//false
System.out.println("比较两个字符串内容是否相等(区分大小写):" + str.equals("1-888abcDEF1-3"));//true
System.out.println("比较两个字符串内容是否相等(不区分大小写):" + str.equalsIgnoreCase("1-888ABCDEF1-3"));//true
System.out.println("判断该字符串是否以某个字符串开头:" + str.startsWith("1-"));//true
System.out.println("判断该字符串是否以某个字符串结尾:" + str.endsWith("1-3"));//true
System.out.println("查询ASCII在字符串中第一次的下标:" + str.indexOf(97));//5
System.out.println("查询字符串在字符串中第一次的下标:" + str.indexOf("8"));//2
System.out.println("查询ASCII在字符串中最后一次的下标:" + str.lastIndexOf(97));//5
System.out.println("查询字符串在字符串中最后一次的下标:" + str.lastIndexOf("8"));//4
System.out.println("获取指定下标上的字符:" + str.charAt(5));
System.out.println(str);//1-888abcDEF1-3
练习:完成一个邮箱格式的校验 hhy@qq.com
(1),“@”不能在第一位
(2),“.”不能在最后一位
(3),“@”和“.”中间应该有字符
(4),***@***.***
当然还有更严格的校验规则,我们此处考虑到这即可
String email = "hhy@qq.com";
int len = email.length();
int index1 = email.indexOf("@");
int index2 = email.indexOf(".");
if(index1 == 0 || index1 == len-1 || index2 == 0 || index2 == len-1 || (index2-index1) < 2){
System.out.println("邮箱格式不正确");
}
StringBuffer的常用方法
-
含义:StringBuffer代表可变的字符序列。
-
StringBuffer称为字符串缓冲区,它的工作原理是:预先申请一块内存,存放字符序列,
-
如果字符序列满了,会重新改变缓存区的大小,以容纳更多的字符序列。
-
StringBuffer是可变对象,这个是String最大的不同
注意:StringBuffer extends AbstractStringBuilder
//默认缓冲区大小16个字符
//StringBuffer sb = new StringBuffer();
//设置指定缓冲区大小
//StringBuffer sb = new StringBuffer(30);
//设置缓冲区大小:"123abcDEF".length() + 16
StringBuffer sb = new StringBuffer("123abcDEF");
sb.append("123");//在末尾追加内容
sb.insert(3, "xxx");//在指定下标上插入字符串
sb.setCharAt(4, '-');//替换指定下标上的字符
sb.replace(3, 6, "xxxyyy");//从开始下标处(包含)替换到结束下标处(不包含)
sb.deleteCharAt(10);//删除指定下标上的字符
sb.delete(3, 9);从开始下标处(包含)删除到结束下标处(不包含)
sb.reverse();//反转字符
System.out.println("获取字符长度:" + sb.length());
System.out.println(sb);//321FEDca321
StringBuilder的常用方法
- 含义:StringBuilder代表可变的字符序列。
- StringBuilder称为字符串缓冲区,它的工作原理是:预先申请一块内存,存放字符序列,
- 如果字符序列满了,会重新改变缓存区的大小,以容纳更多的字符序列。
- StringBuilder是可变对象,这个是String最大的不同
- 注意:StringBuilder extends AbstractStringBuilder
//默认缓冲区大小16个字符
//StringBuilder sb = new StringBuilder();
//设置指定缓冲区大小
//StringBuilder sb = new StringBuilder(30);
//设置缓冲区大小:"123abcDEF".length() + 16
StringBuilder sb = new StringBuilder("123abcDEF");
sb.append("123");//在末尾追加内容
sb.insert(3, "xxx");//在指定下标上插入字符串
sb.setCharAt(4, '-');//替换指定下标上的字符
sb.replace(3, 6, "xxxyyy");//从开始下标处(包含)替换到结束下标处(不包含)
sb.deleteCharAt(10);//删除指定下标上的字符
sb.delete(3, 9);从开始下标处(包含)删除到结束下标处(不包含)
sb.reverse();//反转字符
System.out.println("获取字符长度:" + sb.length());
System.out.println(sb);//321FEDca321
StringBuilder vs StringBuffer
- 注意:使用方式是一样的
- StringBuilder:线程不安全的 – 不上锁 – 快
- StringBuffer:线程安全 – 上锁 – 慢
频繁的字符串拼接使用StringBuilder或StringBuffer
如果程序对附加字符串的需求很频繁,系统会频繁在内存中创建String对象,造成性能下降。所以并不建议使用+来进行频繁的字符串串联
long startTime = System.currentTimeMillis();//获取自1970.1.1 0:0:0到现在的毫秒数
// String str = "邓静涵";
// for (int i = 0; i < 20000; i++) {
// str += "我的小可爱,皇冠给你带";
// //str = str + "我的小可爱,皇冠给你带";
// //str = new StringBuilder(str).append("我的小可爱,皇冠给你带").toString();
// }
StringBuilder sb = new StringBuilder("邓静涵");
for (int i = 0; i < 20000; i++) {
sb.append("我的小可爱,皇冠给你带");
}
long endTime = System.currentTimeMillis();//获取自1970.1.1 0:0:0到现在的毫秒数
System.out.println(endTime - startTime);