包装类与String类
包装类
什么是包装类
Java是面向对象的语言,但并不是“纯面向对象”的,因为我们经常用到的基本数据类型就不是对象。但我们在实际应用中经常需要将基本数据转化成对象,以便于操作
为了解决这个不足,Java在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。8种基本数据类型,分别对应一个包装类。包装类均位于java.lang包
基本数据类型 | 包装类 |
---|---|
byte | Byte |
boolean | Boolean |
short | Short |
char | Character |
int | Integer |
long | Long |
float | Float |
double | Double |
在这八个类名中,除了Integer和Character类以外,其它六个类的类名和基本数据类型一致,只是类名的第一个字母大写而已
在这八个类中,除了Character和Boolean以外,其他的都是“数字型“,“数字型”都是java.lang.Number的子类
为什么需要包装类
优点
- 某些方法的参数必须是对象,为了让基本数据类型的数据能作为参数,提供包装类
- 包装类还可以提供更多的功能
- 其他特别重要的功能:比如可以实现字符串和基本数据类型之间的转换
//只可以是纯数字才可以转成int类型的
String str = "123";
//使用包装类转型
int i = Integer.parseInt(str);
//声明Integer类型的变量
Integer integer = new Integer(10);
//Inteage转String
String s = integer.toString();
注意
注意1:包装类的对象需要占用栈内存和堆内存,而基本数据类型的(局部)变量只占用栈内存;基本数据类型的变量占用空间少,更简单,更灵活,更高效
注意2:作为成员变量,初始值不同。int 0;Integer null
自动装箱和自动拆箱
自动装箱和拆箱就是将基本数据类型和包装类之间进行自动的互相转换。JDK1.5后,Java引入了自动装箱(autoboxing)/拆箱(unboxing)
自动装箱:基本类型的数据处于需要对象的环境中时,会自动转为“对象”
自动拆箱:每当需要一个值时,对象会自动转成基本数据类型,没必要再去显式调用intValue()、doubleValue()等转型方法
如 Integer i = 5;int j = i; 这样的过程就是自动拆箱
我们可以用一句话总结自动装箱/拆箱:
自动装箱过程是通过调用包装类valueOf()方法实现的,而自动拆箱过程是通过调用包装类 xxxValue()方法实现的(xxx代表对应的基本数据类型,如intValue()、doubleValue()等)
//基本类型
int a2 = 20;
//JDK1.5以后提供类自动的装箱操作 valueOf()
Integer integer2 = a2;
//自动拆箱 intValue()
int a3 = integer2;
理解Integer源码
Integer的父类是Number类;底层就是封装了一个int类型的value常量,可以通过构造方法、intValue()等赋值取值
Integer类提供了一个静态内部类IntegerCache,对于定义一个静态数组cache,长度为256,赋值为-128—127。对于自动装箱时如果是-128—127范围内的数据,直接获取数组的指定值;对于这个范围之外的数据,通过new Integer()重新创建对象。这么做的目的是提高效率
注意
- JDK1.5以后,增加了自动装箱与拆箱功能,如:
- Integer i = 100; int j = new Integer(100);
- 自动装箱调用的是valueOf()方法,而不是new Integer()方法。
- 自动拆箱调用的xxxValue()方法。
- 包装类在自动装箱时为了提高效率,对于-128~127之间的值会进行缓存处理。超过范围后,对象之间不能再使用==进行数值的比较,而是使用equals方法
字符串相关类
String类、StringBuilder类、StringBuffer类是三个字符串相关类
String类是的对象代表不可变的字符序列,StringBuilder类和StringBuffer类代表可变字符序列
String类的使用
//声明方式一
String string1 = "weekeight";
//声明方式二
String string2 = new String("weekeight");
//空字符串 是分配了内存地址 但是内容是空的
String string3 = "";
//空对象 没有内存地址
String string4 = null;
System.out.println("-------------【1】String 中最简单的方法---------------");
//输出字符串长度 字符的个数
System.out.println(string1.length());
//判断字符串是否为空
System.out.println(string3.isEmpty());
//判断字符串是xx开始的
System.out.println(string1.startsWith("w"));
//判断字符串是xx结束的
System.out.println(string1.endsWith("t"));
//把字符串内容转成大写(只有英文可以使用)
System.out.println(string1.toUpperCase());
//把字符串内容转成小写(只有英文可以使用)
System.out.println(string1.toLowerCase());
System.out.println("转换完成字符串:"+string1);
System.out.println("-------------------字符串截取方法-------------------");
//根据下标去字符串中字符内容,超过下标直接越界异常
System.out.println(string1.charAt(1));
//截取指定字符串 [开始下标,结束下标)
System.out.println(string1.substring(1, 4));
//截取指定字符串 [开始下标) 一直截取到字符串结束
System.out.println(string1.substring(3));
//返回第一个字符的下标
System.out.println(string1.indexOf("k"));
//从指定的下标开始查询元素
System.out.println(string1.indexOf("e", 3));
//从结尾开始查询元素
System.out.println(string1.lastIndexOf("e"));
//使用场景 网上下载图片命名
String img = "1.jpg";
//最后一个.的下标
int i = img.lastIndexOf(".");
//后缀
String substring = img.substring(i);
//文件的名称 UUID 保证唯一性
String uuid = UUID.randomUUID().toString().replaceAll("-","");
//拼接文件名
String fileName = uuid + substring;
System.out.println(fileName);
方法摘要 | |
---|---|
char | charAt(int index) 返回指定索引处的 char 值。 |
int | compareTo(String anotherString) 按字典顺序比较两个字符串。 |
String | concat(String str) 将指定字符串连接到此字符串的结尾。 |
boolean | contains(CharSequence s) 当且仅当此字符串包含指定的 char 值序列时,返回 true。 |
boolean | endsWith(String suffix) 测试此字符串是否以指定的后缀结束。 |
boolean | equals(Object anObject) 将此字符串与指定的对象比较。 |
boolean | equalsIgnoreCase(String anotherString) 将此 String 与另一个 String 比较,不考虑大小写。 |
int | hashCode() 返回此字符串的哈希码。 |
int | indexOf(int ch) 返回指定字符在此字符串中第一次出现处的索引。 |
int | indexOf(int ch, int fromIndex) 返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索。 |
int | indexOf(String str) 返回指定子字符串在此字符串中第一次出现处的索引。 |
int | indexOf(String str, int fromIndex) 返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。 |
boolean | isEmpty() 当且仅当 length() 为 0 时返回 true。 |
int | lastIndexOf(int ch) 返回指定字符在此字符串中最后一次出现处的索引。 |
int | lastIndexOf(int ch, int fromIndex) 返回指定字符在此字符串中最后一次出现处的索引,从指定索引处开始进行反向搜索。 |
int | lastIndexOf(String str) 返回指定子字符串在此字符串中最右边出现处的索引。 |
int | lastIndexOf(String str, int fromIndex) 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。 |
int | length() 返回此字符串的长度。 |
String | replace(char oldChar, char newChar) 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。 |
String | replace(CharSequence target, CharSequence replacement) 使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。 |
String | replaceAll(String regex, String replacement) 使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。 |
String[] | split(String regex) 根据给定正则表达式的匹配拆分此字符串。 |
boolean | startsWith(String prefix) 测试此字符串是否以指定的前缀开始。 |
boolean | startsWith(String prefix, int toffset) 测试此字符串从指定索引开始的子字符串是否以指定前缀开始。 |
String | substring(int beginIndex) 返回一个新的字符串,它是此字符串的一个子字符串。 |
String | substring(int beginIndex, int endIndex) 返回一个新字符串,它是此字符串的一个子字符串。 |
String | toLowerCase() 使用默认语言环境的规则将此 String 中的所有字符都转换为小写。 |
String | toString() 返回此对象本身(它已经是一个字符串!)。 |
String | toUpperCase() 使用默认语言环境的规则将此 String 中的所有字符都转换为大写。 |
String | trim() 返回字符串的副本,忽略前导空白和尾部空白。 |
理解String类源码
String类是一个final类,意味着该类不能再有子类
String类底层是一个字符数组value。各种方法的操作其实都是对该数组的操作
String类的equals()方法其实就是比较底层的字符数组的各个元素是否相同,只要发现一个字符不相同,就返回false。如果所有字符都相同,返回true。但是如果两个变量指向了同一个字符数组,直接返回true
String类的concat()是创建一个新的字符数组,存放原来字符数组和新加入的字符数组内容,然后以该新数组创建一个新的字符串
JDK9时String类底层由char数组变为byte数组,节省空间,同时通过一个coder成员变量作为编码格式的标识,使用LATIN1还是UTF-16,这个是在String生成时自动的,如果字符串中都是能用LATIN1就能表示的就是0,否则就是UTF-16
使用StringBuilder类
StringBuffer和StringBuilder非常类似,均代表可变的字符序列
这两个类都是抽象类AbstractStringBuilder的子类,方法几乎一模一样
两个类的区别
- StringBuffer JDK1.0提供的类,线程安全,做线程同步检查,效率较低
- StringBuilder JDK1.5提供的类,线程不安全,不做线程同步检查,因此效率较高。 建议采用该类
注意
实际开发中StringBuilder的使用场合:字符串的拼接(SQL语句)
StringBuilder builder = new StringBuilder("123");
builder.append("321");
builder.append("abc");
String str =builder.toString();
理解StringBuilder源码
- StringBuilder类底层和String类一样,也是一个字符数组value,但不是final的。变量count表示的是底层字符数组的元素的真实个数,不是底层字符数组的长度
- 默认数组的长度是16。也可以通过构造方法直接指定初始长度。length()方法返回的是字符数组元素的真实个数,capacity()返回的是底层数组的长度;
- 每次添加字符串时要扩容,扩容的默认策略时候增加到原来长度的2倍再加2
要点
- String:不可变字符序列
- StringBuffer:可变字符序列,并且线程安全,但是效率低
- StringBuilder:可变字符序列,线程不安全,但是效率高(一般用它)