一、字符序列
多个字符按照一定的顺序组成的列表就叫作字符序列
-
String
字符串 -
StringBuffer
字符串缓冲区,是线程安全的 -
StringBuilder
字符串构造器,非线程安全的 -
CharBuffer
字符缓冲区
1.ASII
码
- 0-31、127(共33个)表示不可见字符,如:换行、回车
- 65-90 表示26个大写英文字母
- 97-122表示26个小写英文字母
- 48-57表示10个数字字符’0’ -‘9’
二、String
多个字符按照一定的顺序组成字符序列,默认值是null
(字符串不可变特性)字符串的内容是不会发生改变的,它的对象在创建后不能被更改
原因:字符串内容存储的元素是final修饰的,不可变
- 字符串常量池不存重复的值。
jdk 1.8及之前版本:
private final char value[]; // 用于存放内容,字符串底层其实就是一个字符数组
private int hash; // 用来存放hash值
jdk1.9及以后版本:
private final byte value[]; // 用于存放内容,1.9之后使用字节数组存储
private int hash; // 用来存放hash值
private byte coder; // 编码方式,0 -LATIN1, 1 - UTF-16
> jdk 1.8之前字符串用char储存,jdk 1.9之后字符串用byte储存,为什么要这么改呢?
主要是为了节约
String
占用的内存,占用内存少引发另外一个好处就是减少GC
次数。
众所周知,在大多数 Java
程序的堆里, String
占用的空间最大,并且绝大多数 String
只有 Latin-1
字符,这些 Latin-1
字符只需要1个字节
就够了。 JDK9
之前, JVM
因为 String
使用 char
数组存储,每个 char
占2个字节
,所以即使字符串只需要1字节/字符,它也要按照2字节/字符进行分配,浪费了一半的内存空间。
JDK9
是怎么解决这个问题的呢?一个字符串出来的时候判断,它是不是只有 Latin-1
字符,如果是,就按照1字节/字符
的规格进行分配内存,如果不是,就按照2字节/字符
的规格进行分配( UTF-16 编码
),提高了内存使用率。
为什么用 UTF-16 而不用 UTF-8 呢,这就要从这两个字符集的设计说起了.
UTF-8
实际上是对空间利用效率最高的编码集,它是不定长的,可以最大限度利用内存和
网络。但是这种编码集只能用于传输和存储,并不适合拿来做 String
的底层实现。因为 String
有随机访问的方法
,所谓随机访问,就是 charAt
、 subString
这种方法。如果字符串中的每个字符占用的内存是不定长的,那么进行随机访问的时候,就需要从头开始数每个字符的长度,才能找到你想要的字符。
使用 UTF-16
编码将它们表示并存储为每个字符2个字节。
字符串的声明
//字面量
String 变量名 = "初始值";
//构造创建对象
String 变量名 = new String ("初始值");
例:
//字符串数组
char[] c ={'a', 'b' ,'c'};
String s4 = new String(c);
System.out.println(s4);
//字节数组
byte[] bytes ={97,98,99,100};
String s5 = new String(bytes);
System.out.println(s5);
字符串在内存中的创建
1.当使用双引号直接赋值时,系统会检查该字符串在字符串常量池(串池)中是否存在。不存在,创建新的,存在,复用
2.new
对象时在堆里面,字符串不会复用
字符串的处理
1.包装类
包装类是一种特殊的类,用于将基本数据类型封装成对象
基本类型 | 包装类 |
---|---|
boolean | Boolean |
char | Character |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
默认值是null
1.构造方法(IDK9
之后过时)
Integer
构造方法名:Integer(int value)、Integer(String s).Byte、short、Long、Float、Double、Boolean和Integer类似。
Character只有一个构造方法:Character(char value)
Float 比 Integer多一个:Float(Double value)
int --> Integer
Integer x = new Integer(100);
System.out.println(x);//100
string -->Integer
Integer y = new Integer("123");
System.out.println(y);//123
double -->Double
Integer z = new Integer(1.23);
System.out.println(z);//1.23
2.包装类常量
-
MAX_VALUE 最大值
-
MIN_VALUE 最小值
System.out.println("int 的最大值" + Integer.MAX_VALUE) System.out.println("int 的最小值" + Integer.MIN_VALUE)
3.装箱/拆箱
Java 提供了自动装箱(Autoboxing
)和自动拆箱(Unboxing
)机制,使得基本类型和包装类之间的转换更加方便。
-
装箱:将基本类型转换为对应的包装类对象,是通过包装类.
valueOf
进行的。 -
拆箱:将包装类对象转换为对应的基本类型,是通过 包装类对象.
xxxValue()
进行。
例:
// 自动装箱
Integer i = 90;
//装箱
int a =100;
Integer obj = new Integer(i);
Integer obj2 = new Integer.valueOf(i)
// 自动拆箱
int num = i;
//拆箱
Integer obj3 = new Integer(200);
int j = obj3.intValue();
int k = obj3;//自动拆箱
-
自动装箱:将基本类型自动转换为对应的包装类对象,是通过 包装类.
valueOf
进行的。 -
自动拆箱:将包装类对象自动转换为对应的基本类型,是通过 包装类对象.
xxxValue()
进行。-
=(装箱或拆箱)
-
+、-、*、/、> 、< 、 ==混合运算(拆箱)
-
调用equals进行比较(装箱)
-
ArrayList
、HashMap
等集合类添加基础类型数据时(装箱)
-
3.String
和基本数据类型转换
-
String ——>基本数据类型
使用各自的包装类调用parse×××( ) 方法
char类型通过String类的
charAt(index)
实现String b = "0.9"; double b1 = Double.parseDouble(b) char gender = gender.charAt(0);//括号里是下标
-
基本数据类型——>String
1.通过"+"将基本数据类型与String类型连接,将基本数据类型转换为String
2.通过
String.valueOf(基本数据类型)
方法将基本数据类型转换为Stringbyte b = 1; int a =2; String s = String.valueOf(a);// String str = String.valueOf(b); String.valueOf(true); String.valueOf(1.1);