包装类:
Double d = 100d; //自动装箱 Double.valueOf(100d); Float f = 1.5f; //自动装箱 Float.valueOf(1.5f); Object obj1 = true?new Integer(1):new Double(2.0) //三元运算符是一个整体 就是都算Double类型
包装类方法:
包装类和String类型的相互转换:
//包装类型-->String类型
Integer i =10;
//法一:
String s1 = i.toString();
//法二:
String s2 = String.valueOf(i);
//法三:
String s3 = i + ""; //只是返回了新对象交给了s3,但是i本身是没有变化的
System.out.print(s3);
//String--->包装类
//法一:
Integer j = new Integer(s1); //构造器
//法二
Integer j2 = Integer.parseInt(s2); //自动装箱
Integer类 和 Character类 的常用方法:
System.out.print(Integer.MIN_VALUE); //返回最小值
System.out.print(Integer.MAX_VALUE); //返回最大值
System.out.print(Character.isDigit("a")); //判断是不是数字
System.out.print(Character.isLetter("a")); //判断是不是字母
System.out.print(Character.isUpperCase("a")); //判断是不是大写
System.out.print(Character.isLowerCase("a")); //判断是不是小写
System.out.print(Character.isWhitespace("a")); //判断是不是空格
System.out.print(Character.toUpperCase("a")); //转成大写
System.out.print(Character.toLowerCase("A")); //转成小写
典例:
public void method1(){
Integer i = new Integer(1); //new 一个对象
Integer j = new Integer(1); //new 一个对象
System.out.print(i == j); //用 == 来判断两个对象是不是同一个
//False
Integer m = 1; //底层用Integer.valueOf(1);-->源码:如果是-128~127之间,
//没有真正new,是直接返回的,超出这个区间才是new
Integer n = 1;
System.out.print(m == n); //T
Integer x = 128;
Integer y = 128;
System.out.print(x == y); //F
}
String:
- String对象用于保存字符串,也就是一组字符序列
-
字符串常量对象是用双引号括起的字符序列。例如:”你好”、”12.97″、”key”等
-
字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节
-
String类较常用构造方法(其他看手册)
String s1 = new String(); String s2 = new String(String original); String s3 = new String(char[] a); String s4 = new String(char[] a,int startIndex,int count); //这个char数组从哪里开始,到多少个结束
- String类实现了接口 Serializable (String 可以串行化:可以在网络传输)
-
String类实现了接口 Comparable (String 对象可以比较大小)
-
String类是final类,不能被继承
-
String 有属性 private final char value[];用于存放字符串内容
-
注意:value是一个final类型,赋值后就不能修改(指地址不能修改,但地址里的内容可以修改)
如:
System name = "jack"; name = "tom"; final char[] value = {"a","b","c"}; value[0] = "h"; //仍可以运行 char[] v2 = {"t","o","m"}; value = v2; //会报错
创建String对象的两种方式:
- 方式一:直接赋值 String s = “hspedu”;
先从常量池查看是否有”hsp”数据空间,如果有,直接指向;如果没有则重新创建,然后指向,s最终指向的常量池的空间地址
-
方式二:调用构造器 String s = new String(“hspdu”);
现在堆中创建空间,里面维护了value属性,指向常量池的hsp空间。如果常量池没有”hsp”,重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址。
习题1:
String a = "abc";
String b = "abc";
System.out.print(a.equals(b)); //T
System.out.print(a == b); //T
习题2:
String a = new String("abc");
String b = new String("abc");
System.out.print(a.equals(b)); //T
System.out.print(a == b); //F
习题3:
String a = "hsp"; //a指向常量池的"hsp"
String b = new String("hsp"); //b指向堆中的对象,堆中对象的value再指向常量池的"hsp"
System.out.print(a.equals(b)); //T
System.out.print(a == b); //a直接指向常量池,b指向堆,堆中的value才是指向常量池
/*
当调用intern方法时,如果池已经包含一个等于此String对象的字符串(用equals(Object)方法确定),
则返回来自池的字符串,否则,此String对象将添加到池中,并返回对此String对象的引用。
*/
System.out.print(a == b.intern()); //T
System.out.print(b == b.intern()); //F
//b指向堆,b.intern()指向常量池
b.intern()方法最终返回的时常量池的地址(对象)
习题4:
String s1 = "hspedu";
String s2 = "java";
String s4 = "java";
String s3 = new String("java");
System.out.print(s2 == s3); //F
System.out.print(s2 == s4); //T
System.out.print(s2.equals(s3)); //T s2和s3的内容
System.out.print(s1 == s2); //F
/*
s3指向堆,堆中value指向常量池
s1,s2,s4指向常量池
*/
习题5:
Preson p1 = new Person();
p1.name = "hspedu";
Preson p2 = new Person();
p2.name = "hspedu";
System.out.print(p1.name.equals(p2.name)); //T 比较的是内容,都是"hspedu"
System.out.print(p1.name == p2.name); //T //p1指向堆,堆中p1的name指向常量池的"hspedu"
//p2指向堆,堆中p2的name指向常量池的"hspedu"
System.out.print(p1.name == "hspedu"); //T
String s1 = new String("bcde");
String s2 = new String("bcde");
System.out.print(s1 == s2); //F s1指向堆,堆中value指向常量池的"bcde,
// s2指向堆,堆中value指向常量池的"bcde
// 但s1,s2指向的是不同的对象
字符串的特性:
-
String是一个final类,代表不可变的字符序列
-
字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的
String s1 = "hello"; s1 = "haha"; /* 创建了两个对象, s1指向常量池里的"hello", s1 = "haha"; 语句执行后,在常量池又创建一个"haha",s1指向常量池里的"haha",不指向"hello", 而此时,常量池里有两个对象,"hello"和"haha" */
题1:
String a = "hello" + "abc";
/*
编译器会直接优化,等价于String a = "helloabc"
只创建了一个对象
*/
题2:
String a = "hello"; //创建a对象
String b = "abc"; //创建b对象
String c = a + b;
/* 1、先创建一个 StringBuilder sb = StringBuilder();
2、执行 sb.append("hello");
3、sb.append("abc");
4、String s = sb.toString;
最后其实是 c 指向堆中的对象(String) value[]-->池中"helloabc"
a指向常量池的"hello"
b指向常量池的"abc"
c指向堆,堆中的value指向常量池的"helloabc"*/
题3:
String s1 = "hspedu"; //指向池中"hspedu"
String s2 = "java"; //指向池中"java"
String s5 = "hspedujava"; //指向池中"hspedujava"
String s6 = (s1 + s2).intern(); //指向池中"hspedujava"
System.out.print(s5 == s6); //T
System.out.print(s5.equals(s6)); //T
题4:
public class Test1{
String str = new String("hsp");
final char[] ch = {"j","a","v","a"};
public void change(String str,char ch[]){
str = "java";
ch[0] = "h";
}
public static void main(String[] args) {
Test1 ex = new Test1();
ex.change(ex.str,ex.ch);
System.out.print(ex.str + "and");
System.out.print(ex.ch); //输出:hspandhava
}
}
String类的常见方法:
String类是保存字符串常量的。每次更新都需要重新开辟空间,效率较低,因此java设计者还提供了StringBuilder 和 SreingBuffer 来增强String的功能,并提高效率。
equals //区分大小写,判断内容是否相等
equalslgnoreCase //忽略大小写的判断内容是否相等
length //获取字符的个数,字符串的长度
indexOf //获取字符在字符串中第1次出现的索引,索引从0开始,如果找不到,返回-1
lastIndexOf //获取字符在字符串中最后1次出现的索引,索引从0开始,如果找不到,返回-1
substring //截取指定范围的字串
substring(6) //索引从6开始截取后面所有的内容
substring(2,5) //索引从0开始截取,截取到 索引 5-1=4 的位置
trim //去掉前后空格
charAt //获取某索引处的字符,注意不能使用Str[index]这种方式
String str = "hello";
str[0]; //不对,这样把str当数组了
str.charAt(0)==>h
toUpperCase //转换成大写
toLowerCase //转换成小写
concat //拼接字符串
String s1 = "宝玉";
s1 = s1.concat("林黛玉").concat("薛宝钗").concat("together");
System.out.print(s1); //宝玉林黛玉薛宝钗together
replace //替换字符串中的字符
注:replace方法执行后,返回的结果才是替换过的,对s1没有任何影响
s1 = "宝玉 and 林黛玉 林黛玉";
s1 = s1.replace("林黛玉","薛宝钗")
//在s1中,将所有的 林黛玉 替换成 薛宝钗
System.out.print(s1); //宝玉 and 薛宝钗 薛宝钗
split //分割字符串,对某些分割字符,我们需要 转义 比如 | \\等
String poem = "锄禾日当午,汗滴禾下土,谁之盘中餐,粒粒皆辛苦";
String[] split = poem.split(","); //以","为分割,返回一个数组
for (int i = 0;i < split.length ;i++ ) {
System.out.print(split[i]);
}
/*
输出结果:
锄禾日当午
汗滴禾下土
谁之盘中餐
粒粒皆辛苦
*/
toCharArray //转换成字符数组
compareTo //比较两个字符串的大小;如果前者大,就返回正数,后者大,返回负数;如果相等则返回0
1、如果长度相同,并且每个字符也相同,就返回0;
2、如果长度相同或者不相同,但是在进行比较时,可以区分大小,
就返回 if(c1 != c2){
return c1 - c2;
}
3、如果前面的部分都相同,就返回 str1.len - str2.len
format //格式字符串
/*
占位符有:
%s 字符串;
%c 字符;
%d 整形;
%.2f 浮点型;
String info2 = String.format("我的姓名是%s 年龄是%d 成绩是%.2f 性别是%c",namenage,score,gender)
*/
StringBuffer类
java.lang.StringBuffer 代表可变的字符序列,可以对字符串内容进行增删
很多方法与String相同,但StringBuffer是可变长度的
StringBuffer是一个容器
- StringBuffer 的直接父类 是AbstractStringBuilder
- StringBuffer 实现了接口 Serializable (String 可以串行化:可以在网络传输)
- 在父类中,AbstractStringBuilder 有属性 char[] value,不是final,该value数组存放字符串内容,引出存放在堆中的
- StringBuffer 是一个final类,不能被继承
- 因为StringBuffer字符内容是存在char[] value,所有在变化(增加/删除)不用每次都更换地址(即不是每次创建新对象),所以效率高于String
StringBuffer的构造器:
StringBuffer() //构造一个其中不带字符的字符串缓冲区,其初始容量为16个字符
StringBuffer(CharSequence seq)
public java.lang.StringBuilder(CharSequence seq)构造一个字符串缓冲区,它包含与指定的CharSequence相同的字符
StringBuffer(int capacity) //capacity[容量]
//构造一个不带字符,但具有指定初始容量的字符串缓冲区。即对char[]大小进行指定
StringBuffer(String str)
//构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容
String 和 StringBuffer相互转换:
//String--->StringBuffer
String s = "hello";
//方式1:
//注意:返回的才是StringBuffer对象,对b1本身没影响
StringBuffer b1 = new StringBuffer(s);
//方式2:
StringBuffer b2 = new StringBuffer();
b2.append(s);
//StringBuffer--->String
//方式1:
String s2 = b1.toString(); //b1[StringBuffer]
//方式2:
String s3 = new String(b1); //使用构造器
StringBuffer常用方法:
- 增 append
-
删 delete(start,end)
s.delete(11,14) //删除索引为 start <= 索引 < end
-
改 replace(start,end,string)
//将start—end间的内容替换掉,不含end
-
查 indexOf //查找字串在字符串第一次出现的索引,如果找不到返回-1
-
插 insert
s.insert(9,”赵敏”); //在索引为9的位置插入”赵敏”,原来索引为9的内容自动后移
-
获取长度 length
String VS SreingBuffer:
-
String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上就是更改地址,效率较低
//private final char value[];
-
StringBuffer保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新实际上可以更新内容,不用每次更新地址,效率较高
//char[] value; 这个放在堆
StringBuilder类:
StringBuilder 和 StringBuffer 均代表可变的字符序列,方法是一样的,所以使用和StringBuffer一样
- 一个可变的字符序列。此类提供一个与StringBuffer兼容的API,但不保证同步,(StringBuilder不是线程安全的)
该类被设计用作StringBuffer的一个建议替换,用在字符串缓冲区被单个线程使用的时候。
如果可能,建议优先采用该类,因为在大多数实现中,它比StringBuffer要快
-
在StringBuilder上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据
String、StringBuffer、StringBuilder的比较:
-
StringBuffer和StringBuilder非常类似,均代表可变的字符序列,而且方法也一样
-
String:不可变字符序列,效率低,但是复用率高
-
StringBuffer:可变字符序列,效率较高(增删)、线程安全
-
StringBuilder:可变字符序列,效率最高、线程不安全
-
String使用注意说明:
String s = "a"; //创建了一个字符 s += "b"; /* 实际上原来的"a"字符串对象已经丢弃了, 现在又产生了一个字符串 s += "b"(也就是ab)。如果多次执行这些改变串内容的操作, 会导致大量副本字符串对象留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的性能 结论:如果我们对String做大量修改,不要使用String */
String、StringBuffer、StringBuilder的选择:
- 如果字符串存在大量的修改操作,一般使用StringBuffer或StringBuilder
- 如果字符串存在大量的修改操作,并在单线程的情况,StringBuilder
- 如果字符串存在大量的修改操作,并在多线程的情况,StringBuffer
- 如果我们字符串很少修改,被多个对象引用,使用String,比如配置信息等