学习目录
一、包装类
1.基本介绍
包装类是针对八种基本数据类型相对应的引用类型,主要的特点就是调用该类中的方法
基本数据类型 | 包装类 |
---|---|
boolean | Boolean |
char | Character |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
除了Boolean和Character其余包装类的父类都是Number
2.装箱和拆箱
装箱:基本数据类型 转换成 包装类型
拆箱:包装类型 转换成 基本数据类型
jdk5以前需要手动的装箱和拆箱,jdk5以后可以自动装箱和拆箱
这里以int类型为例,其他类似
class test1{
public static void main(String[] args) {
//手动装箱 int -> Integer
int a = 10;
//方法一
Integer integer = new Integer(a);
//方法二
Integer integer1 = Integer.valueOf(a);
//手动拆箱 Integer -> int
int i = integer.intValue();
//jdk1.5以后自动拆装箱
//自动装箱,底层代码仍是调用Integer.valueOf()
Integer Integer2 = a;
//自动拆箱,底层代码仍是调用integer.intValue()
int a2 = Integer2;
}
}
包装类与String之间的转换,这里以Integer为例
class test1{
public static void main(String[] args) {
//Integer -> String
Integer i = 10; //这里是自动装箱
//方法一
String s = i +"";
//方法二
String s1 = i.toString();
//方法三
String s2 = String.valueOf(i);
//String -> Integer
String st = "123";
//方法一
Integer i1 = Integer.parseInt(st); //本身返回的是Int类型,然后自动装箱为Integer
//方法二
Integer integer = new Integer(st); //源码为调用它的一个构造器
//常用的方法
System.out.println(Integer.MAX_VALUE); //表示的最大值
System.out.println(Integer.MIN_VALUE); //表示的最小值
System.out.println(Character.isDigit('c')); //判断是不是数字
System.out.println(Character.isDigit('c')); //判断是不是字母
System.out.println(Character.isUpperCase('c')); //判断是不是大写
System.out.println(Character.isLowerCase('c')); //判断是不是小写
}
}
面试题1
Object x = true ? new Integer(1) : new Double(2.0);
System.out.println(x); //因为x后面的是三元运算符,所以数据类型取最大的,
面试题2
class test1{
public static void main(String[] args) {
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j); //false,因为是new了两个不同的对象
/*
Integer m = 1完成了自动装箱功能,调用了Integer.valueOf(1)方法
该方法源码的意思为:
如果给的这个数在-128-127之间那么直接从返回
如果给的这个数不在-128-127之间,那么要new Integer(i),
如果是new Integer(i)的话就是两个不同的对象了
*/
Integer m = 1; //底层 Integer.valueOf(1);
Integer n = 1; //底层 Integer.valueOf(1);
System.out.println(m == n); //true
Integer m1 = 128; //底层 Integer.valueOf(1);
Integer n1 = 128; //底层 Integer.valueOf(1);
System.out.println(m1 == n1); //false
int x = 128;
Integer y = 128;
System.out.println(x == y); //true 因为x为基本数据类型,所以比较的是值是否相等
}
}
二、String类☆
1.基本介绍
- String 对象用于保存字符串,也就是一组字符序列
- 字符串的字符使用 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);
⑤String s5 = new String(byte[] b); - String类实现了接口Serializable和Comparable
①Serializable:String 可以串行化,可以在网络传输
②Comparable :String 对象可以比较大小 - String 是 final 类,不能被其他的类继承
- String 有个属性为 private final char value[],用于存放字符串内容,在源码的114行;注意:value是一个final可惜,不可以修改,即value不能指向新的地址,但是单个字符内容是可以修改的,代码演示如下
class test1{
public static void main(String[] args) {
final char[] value = {'a','b','c'};
char[] value1 = {'t','o','m'};
value[0] = 'H'; //final char[] value = {'H','b','c'};
// value = value1; //错误的
}
}
2.创建String对象的两种方式
方式一:直接赋值 如:String s = “java”;
方式二:调用构造器 如:String s = new String(“java”);
两者之间的区别:
方式一:先从常量池查看是否有"java"数据空间,如果有就指向,如果没有就重写创建。s最终指jvm方法区常量池中的空间地址
方式二:先在jvm堆中创建空间,里面维护了 private final char value[] 属性,然后指向常量池"java"数据空间,如果有通过value指向,如果没有则重新创建。最终指向的是堆中的空间地址
测试题
class test1{
public static void main(String[] args) {
//equals比较两个值是否相等
//intern方法最终返回是常量池的地址
//测试一 a和b都指向常量池的同一个地址
String a = "java";
String b = "java";
System.out.println(a.equals(b)); //true
System.out.println(a == b); //true
//测试二
String a1 = new String("java");
String b1 = new String("java");
System.out.println(a1.equals(b1)); //true
System.out.println(a1 == b1); //false 创建了两个对象
//测试三
String a2 = "java";
String b2 = new String("java");
System.out.println(a2.equals(b2)); //true
System.out.println(a2 == b2); //false 一个常量池,一个堆中对象
System.out.println(a2 == b2.intern()); //true
System.out.println(b2 == b2.intern()); //false
//测试四
String a3 = "Test";
String b3 = "java";
String c3 = new String("java");
System.out.println(a3 == b3); //false
System.out.println(b3.equals(c3)); //true
System.out.println(b3 == c3); //false
//测试五
test test1 = new test();
test test2 = new test();
test1.name = "java";
test2.name = "java";
System.out.println(test1.name.equals(test2.name)); //true
System.out.println(test1.name == test2.name); //true
System.out.println(test1.name == "java"); //true
}
}
class test{
String name;
}
3.String字符串的特性
- String是一个final类,代表不可变的字符系列
- 字符串是不可变的,一个字符串对象一旦被分配,其内容是不可变的
面试题
class test1{
public static void main(String[] args) {
//下面代码创建了几个对象? 2
String s = "test";
s = "ssss";
//下面代码创建了几个对象? 1
String s1 = "java" + "test"; //在底层编译器会优化 String s1 = "javatest";
//下面代码创建了几个对象? 3
String s2 = "java";
String s3 = "test";
/*
debug追源码
1.先创建一个StringBuilder x = StringBuilder()
2.执行x.append("java");
3.执行x.append("test");
4.String s4 = x.toString() 而toString里面是有一个new的过程
*/
String s4 = s2 + s3;
//测试题
String s5 = "javatest";
System.out.println(s4 == s5); //false
String s6 = "java"+"test";
System.out.println(s5 == s6); //true,因为直接指向常量池中的同一个地址
}
}
String s6 = “java”+“test”; 常量相加看池,String s4 = s2 + s3; 变量相加看堆
测试题
class test1{
public static void main(String[] args) {
String s = "java"; //指向常量池中的 "java"
String s1 = "test"; //指向常量池中的 "test"
String s2 = "javatest"; //指向常量池中的 "javatest"
String s3 = (s+s1).intern(); //指向常量池中
System.out.println(s2 == s3); //true
System.out.println(s2.equals(s3)); //true
}
}
4.String的常用方法
方法名 | 功能 |
---|---|
equals | 区分大小写,判断内容是否相等 |
equalslgnoreCase | 不区分大小写,判断内容是否相等 |
length | 获取字符的个数,字符串的长度 |
indexOf | 获取字符在字符串中第1次出现的索引,如果找不到返回-1 |
lastIndexOf | 获取字符在字符串中最后1次出现的索引,如果找不到返回-1 |
substring | 截取指定范围的字串 |
trim | 去前后空格 |
charAt | 获取某索引处的字符,注意不能使用Str[index]这种方式 |
toUpperCase | 转化为大写 |
toLowerCase | 转化为小写 |
concat | 字符串的拼接 |
replace | 替换字符串中的字符 |
split | 分割字符串 |
compareTo | 比较两个字符串的大小 |
toCharArray | 转换成字符数组 |
format | 格式字符串 |
三、StringBuffer类☆
1.基本介绍
引入:String类是保存字符常量的,每次更新都需要重新开辟空间,效率较低,因此java设计者提供了StringBuffer和StringBuilder来增强String的功能,并提高效率
StringBuffer代表可变的字符序列,可以对字符串内存进行增删,很多方法与String相同,但StringBuffer是可变长度的
StringBuffer是一个容器
StringBuffer解析:
- StringBuffer 的直接父类是 AbstractStringBuilder
- StringBuffer 实现了 Serializable,即 StringBuffer 的对象可以串行化(进行网络传输)
- 在父类中 AbstractStringBuilder 有个属性 char[] value,不是 final,该value数组存放字符串内容,即存放在堆中
- StringBuffer是一个 final 类,不能被继承
String与StringBuffer的比较
- String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上就是更改地址,效率较低
- StringBuffer保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新实际上可以更新内容,不用每次更新地址,效率较高
StringBuffer常用构造器
- StringBuffer():构造一个不带字符的字符串缓冲区,其初始容量为16个字符
- StringBuffer(int capacity):构造一个不带字符,但具有指定初始容量的字符串缓冲区,即对char[]大小进行指定
- StringBuffer(String str):构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容
String和StringBuffer相互转换
class test1{
public static void main(String[] args) {
//String -> StringBuffer
//方式一
String s = "java";
StringBuffer stringBuffer = new StringBuffer(s);
//方式二
StringBuffer stringBuffer1 = new StringBuffer();
stringBuffer1.append(s);
//StringBuffer -> String
//方式一
StringBuffer stringBuffer2 = new StringBuffer("java");
String s1 = stringBuffer2.toString();
//方式二
String s2 = new String(stringBuffer2);
}
}
2.StringBuffer常用方法
增、删、改、插以及获取长度等
class test1{
public static void main(String[] args) {
//增
StringBuffer s = new StringBuffer("java");
s.append(",");
s.append("test").append(1);
System.out.println(s);
//删
StringBuffer s1 = new StringBuffer("java");
s1.delete(0, 2);
System.out.println(s1);
//改
StringBuffer s2 = new StringBuffer("java");
s2.replace(0,1,"AA");
System.out.println(s2);
//插
StringBuffer s3 = new StringBuffer("java");
s3.insert(1,"BB");
System.out.println(s3);
//获取长度
System.out.println(s3.length());
}
}
四、StringBuilder类☆
1.基本介绍
StringBuilder一个可变的字符序列。此类提供一个与StringBuffer兼容的API,但不保证同步(StringBuilder 不是线程安全) 该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。其主要用法和StringBuffer一样
如果可以使用StringBuilder ,建议优先采用该类,因为在大多数实现中,它比StringBuffer要快
在StringBuilder上的主要操作是append和insert方法,可重载这些方法,以接收任意类型的数据
StringBuilder解析:
- StringBuffer 的直接父类 是 AbstractStringBuilder
- StringBuffer 实现了 Serializable, 即 StringBuffer 的对象可以串行化
- StringBuilder 对象字符序列仍然是存放在其父类 AbstractStringBuilder 的 char[] value;因此,字符序列是堆中
- StringBuilder 的方法,没有做互斥的处理,即没有 synchronized 关键字,因此在单线程的情况下使用
2.String、StringBuffer 和 StringBuilder 的比较
- StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且方法一样
- String:不可变字符序列,效率低,但是复用率高
- StringBuffer:可变字符序列、效率较高(增删)、线程安全
- StringBuilder:可变字符序列、效率最高、线程不安全
3.总结☆
- 如果字符串存在大量的修改操作,一般使用StringBuffer和StringBuilder
- 如果字符串存在大量的修改操作,并在单线程的情况,使用StringBuilder
- 如果字符串存在大量的修改操作,并在多线程的情况,使用StringBuffer
- 如果我们字符串很少修改,被多个对象引用,使用String,比如 配置信息等