String
String概述
- 软件包在java.lang包下,使用时不需要导包
- String类代表字符串,java程序中的所有字符串文字都被实现为此类的对象。例如“abc”就是String类的对象 = java程序中所有双引号字符串都是String类的对象。
- 特点:
①字符串不变,在创建后不能被更改;
②String的值不可以更改,但是它们可以被共享;(在常量池中被共享)
③字符串效果上相当于字符数组(char[]),但是底层原理是字节数组(byte[]);JDK8以及之前是字符数组,JDK9及以后是字节数组。
String构造方法
方法名 | 说明 |
---|---|
public String() | 创建一个空白字符串对象,不含有任何内容 |
public String(char[] chs) | 根据字符数组的内容,来创建字符串对象 |
public String(byte[] bys) | 根据字节数组的内容,来创建字符串对象 |
public String (byte[] bys , int beginIndex,int len) | 根据字符数组的内容,从beginIndex索引处开始的len长度的数组创建字符串 |
String s = “abc” | 直接赋值的方式创建字符串对象,内容就是abc |
推荐直接使用直接赋值的方式创建字符串对象
案例:
// 112-StringDemo
public class StringDemo {
public static void main(String[] args){
//通过无参构造方法创建对象
String str = new String();
System.out.println("str:" + str);//输出str:
//通过 String(char[] chs),通过字符数组创建字符串对象
//创建字符数组
char[] arr = {'a','b','c'};
String str1 = new String(arr);
System.out.println("str1:" + str1);//输出str1:abc
//通过String(byte[] bys),通过字节数组创建字符串对象
byte[] bys = {97,98,99};//字节数组存储内容是数据,也就是字符在计算机低层存储的对应值。97对应的是a
String str2 = new String(bys); // 创建字符串时。会转换为数值对应的字符
System.out.println("str2:" + str2);//str2:abc
// 直接通过 = “字符串”
String str3 = "abc";
System.out.println("str3:" + str3);//str3:abc
}
}
String对象的特点
- 通过new创建的字符串对象(利用字符相同的字符数组),每一次new都会申请一个堆内存空间,虽然内容相同,但是地址值不同。
char[] chs = {'a','b','c'};
String s1 = new String(chr);
String s2 = new String(chr);
解释:JVM会首先创建一个字符数组,然后每一次new的时候都会有一个新的地址,只不过s1和s2参考的字符串内容是相同的。
- 以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM都只会创建一个String对象,并在常量池中维护。
String s3 = “abc”;
String s4 = “abc”;
理解:
针对第一行代码,JVM会建立一个String对象放在字符串池中,并将地址值赋给s3;
第二行执行,JVM会先查看常量池中是否有“abc”,发现有,则会将对应的地址赋值给s4,也就是说它们本质上是同一个对象。
内存示例图:
提到常量池
案例:
// 112-StringDemo1
public class StringDemo1 {
public static void main(String[] args){
//通过构造方法创建对象 字符数组创建
char[] chs = {'a','b','c'};
String str1 = new String(chs);
String str2 = new String(chs);
System.out.println(str1 == str2);//false
//通过字符串直接赋值的方式创建对象
String str3 = "abc";
String str4 = "abc";
System.out.println(str3 == str4);//true
System.out.println(str1 == str3);//false
}
}
String的比较
使用==做比较
- 基本类型:比较的是数据值是否相同
- 引用类型:比较的是地址值是否相同
字符串内容比较
- 由于字符串是引用类型,使用==符号只能比较地址是否相同。
- 字符串是对象,它比较内容是否相同,是通过一个方法来实现的,这个方法叫equals()
public boolean equals(Object anObject)
将此字符串与指定对象进行比较,由于比较的是字符串,所以参数直接传递一个字符串。
案例:字符串对象的地址、内容比较
// 112
//字符串地址 内容的比较
public class StringDemo2 {
public static void main(String[] args){
//构造方法得到对象
char[] chs = {'a','b','c'};
String str1 = new String(chs);
String str2 = new String(chs);
//直接赋值得到的对象
String str3 = "abc";
String str4 = "abc";
//比较地址
System.out.println(str1 == str2);//false
** 由于采用构造方法的方式得到对象,不同的对象会在堆内存中开辟不同的存储空间,所以地址不一样。
System.out.println(str3 == str4);//true
** 采用直接赋值的方式,字符串会在堆内存中的常量池存储,对应有地址;
** 使用直接赋值的方式,若两个对象所要赋值的字符串相同(顺序以及大小写相同),那么两个对象在栈内存所存储的堆内存的地址是一样的。
System.out.println(str1 == str3);//false
** 构造方法创建对象、直接赋值方法创建对象都会另开辟内存空间的。所以地址是不同的
System.out.println("-----------");
比较内容,主要判断字符串中字符的顺序和大小写是否一致。
System.out.println(str1.equals(str2));//true
System.out.println(str1.equals(str3));//true
System.out.println(str3.equals(str4));//true
}
}
String中常用方法
方法名 | 说明 |
---|---|
返回数组 | – |
char[] toCharArray() | 将此字符串转换为新的字符串数组 |
byte[] getBytes() | 使用平台默认字符集将此String编码为byte序列,并将结果存储到一个新的byte数组中 |
String[] split(String regex) | 根据给定正则表达式的匹配拆分此字符串 |
返回boolean | – |
public boolean equals(Object anObject) | 比较字符串的内容,严格区分大小写 |
boolean startsWith(String prefix) | 检测此字符串是否以指定的前缀开始 |
返回String | – |
static String valueOf(数据类型 变量名) | 返回(数据类型)参数的字符串表示形式 |
String concat(String str) | 将指定字符串str连接到此字符串的结尾 |
String intern() | 返回字符串对象的规范化表示形式 |
String replace(char oldchar,char newChar) | 返回新的字符串,通过newchar替换掉oldchar得到 |
String replaceAll(String regex,String replacement) | 使用给定replacement替换此此字符串所有匹配给定的正则表达式的子字符串 |
String substring(int beginIndex) | 返回新字符串,是此字符串的子字符串,从下标beginIndex开始 |
String substring(int beginIndex,int endIndex) | 返回新字符串,从下标beginIndex开始到endIndex |
String trim() | 返回字符串的副本,忽略前导空白 和 尾部空白 |
返回int或char | – |
int indexOf(String str) | 返回指定字符串str在此字符串中第一次出现处的索引 |
int indexOf(int ch) | 返回指定字符第一次出现在字符串内的索引 |
int lastIndexOf(int ch) | 返回指定字符在此字符串中最后一次出现处的索引 |
public char charAt(int index) | 返回指定索引处的char值 |
public int length() | 返回此字符串的长度 |
int compareTo(String str) | 按字典顺序比较两个字符串 TreeSet集合排序 |
案例
案例1:用户登录
需求:
已知用户名和密码,请用程序实现模拟用户登录,总共给三次机会,登录之后,给出相应的提示。
思路:
1 定义两个字符串表示用户名和密码
String user = “”
String password = “”
2 使用for循环模拟错误登录次数
for(int i = 0 ; i < 3 ; i++)
{
3 通过键盘录入用户登录信息
Scanner sc = new Scanner(System.in);
String userInput = sc.nextLine();//方法nextLine获取输入字符串
String passwordInput = sc.nextLine();
4 通过if-else分支语句判断是否登录成功,成功给出提示,不成功给出登录剩余次数
字符串的内容判断使用equals
if(userInput.equals(users) && passwordInput.equals(password)){
登录成功;
break;//跳出循环
}else{
if(i==2){//说明三次登录已经都用完了
告诉用户账户被锁定;
}else{
输出剩余登录次数 = 2-i 次;
}
}
// 113-StringTest1
//用户登录案例
public class StringTest1 {
public static void main(String[] args){
//定义两个字符串,表示已知的用户名和密码
String user = "xhj";
String password = "123456";
//用循环实现多次比较,比较次数是固定的,使用for循环实现,如果键盘录入内容和已知内容相同则break退出.
for(int i = 0; i < 3;i++){
//键盘输入要登录的用户名和密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String userInput = sc.nextLine();
System.out.println("请输入密码:");
String passwordInput = sc.nextLine();
//拿键盘录入的用户名和密码 与 已知的用户名和密码 进行比较并给出相应的提示,字符串内容的比较是 equals()方法实现
if(userInput.equals(user)&&passwordInput.equals(password)){
System.out.println("登录成功");
break;
}else{
if((2-i)==0){
System.out.println("你的账户已被锁定,请联系管理员解锁");
}else{
//分析:机会 2 1 0
// i 0 1 2
System.out.println("输入的用户名和密码有误,你还有" +(2 -i) + "次机会");
}
}
}
}
}
案例2:遍历字符串
所涉及内容
public char charAt(int index)
返回指定索引处的char值,字符串的索引也是从0开始的
public int length()
返回此字符串的长度
数组的长度:数组名.length
字符串的长度:字符串对象.length()
遍历字符串的通用格式
for(int i = 0;i<string.length();i++){
string.charAt(i);
指定索引处的字符串值。
}
案例:遍历字符串
需求:键盘录入一个字符串,使用程序实现在控制台遍历该字符串
思路:
1 键盘录入一个字符串
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
2 使用for循环遍历字符串
s.length() // 得到字符串长度,进而得到字符串的索引
s.charAt(int index) // 通过索引得到字符串中对应的字符
for(int i = 0;i<s.length();i++){
char c = s.charAt(i);
// 113-StringTest2
// 遍历字符串
public class StringTest2 {
public static void main(String[] args){
//键盘输入一个字符串,通过Scanner获取
Scanner sc = new Scanner(System.in);
//输入字符串的提示符
System.out.println("请输入一个字符串:");
String str = sc.nextLine();
//遍历字符串元素的通用格式
//遍历字符串,获取字符串的长度,public int length()
for(int i = 0;i < str.length();i++){
//遍历字符串,获取字符串中的每一个字符,通过public char charAt(int index)方法
System.out.println(str.charAt(i));
}
}
}
案例3:统计字符次数
需求:键盘录入一个字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的次数(不考虑其他字符)
思路:
1 键盘录入一个字符串
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
2 定义三个变量用于存放字符个数
int upperSum = 0;
int lowerSum = 0;
int numberSum = 0;
3 遍历字符串中的每个字符
for(int i = 0;i<s.lenght();i++)
{
char c = s.charAt(i);
4 判断是否是对应字符,是的话 统计个数的变量+1
if(char >= 'A' && char <= 'Z'){
upperSum++;
}else if(char >= 'a' && char <= 'z'){
lowerSum++;
}else if(char >= '0' && char <= '9'){
numberSum++;
}
// 113-StringTest3
//统计字符次数
public class StringTest3 {
public static void main(String[] args){
// 键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String ch = sc.nextLine();
// 统计大写字母、小写字母、数字字符的个数,定义三个变量
int sumBig = 0;
int sumSmall = 0;
int sumNumber = 0;
//遍历字符串,得到每一个字符
for(int i = 0;i<ch.length();i++){
char xChar = ch.charAt(i);
//判断字符是否属于要统计的字符类型,属于的,对应统计变量+1
//大写字母:ch>='A' && ch<='Z'
//小写字母:ch>='a' && ch<='z'
//数字字符:ch>='0' && ch<='9'
if(xChar >= 'A' && xChar <= 'Z'){
sumBig++;
}else if(xChar >= 'a' && xChar <='z'){
sumSmall++;
}else if(xChar >= '0' && xChar <= '9'){
sumNumber++;
}
}
//输出对应字母的统计数
System.out.println("大写字母的数量:" + sumBig);
System.out.println("小写字母的数量:" + sumSmall);
System.out.println("数字字符的数量:" + sumNumber);
}
}
案例4:拼接字符串
需求:定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果。例如:数组为int[] arr = {1,2,3};,执行方法后的输出结果为:[1,2,3]
思路:
1 定义int类型数组
int[] arr = {'1','2','3'};
2 使用for循环遍历数组获取每个元素
for(int i = 0 ; i<arr.length(); i++){
3 按照指定的格式输出元素 这部分和案例讲解不一样 方式一
System.out.print("[");
if(i!=arr.length -1){
System.out.print(arr[i] + ",");
}else{
System.out.print(arr[i]);
}
System.out.println("]")
3 方式二
String str = "[";
if(i != arr.length-1){
str = str + arr[i] + ",";
}else{
str = str + arr[i];
}
str = str + "]";
System.out.println(str);
}
// 113-StringTest4
//字符串拼接
public class StringTest4 {
//需求:定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果。例如:数组为int[] arr = {1,2,3};,执行方法后的输出结果为:{1,2,3}
public static void main(String[] args){
//使用静态初始化方式定义数组
char[] arr = {'a','b','c','d'};
//调用方法,用字符串变量接收
String str0 = addString(arr);
//输出字符串
System.out.println("数组转后的字符串为:" + str0);
}
//定义方法,用于实现数组按指定要求拼接字符串,返回字符串;返回值类型String
//参数类型 char[] arr
//方法:通过遍历数组元素,按要求拼接成字符串,方法中定义字符串用于拼接数组
public static String addString(char[] arr){
String str = "[";
for(int i = 0;i<arr.length;i++){
if(i == arr.length - 1){
str = str + arr[i];
}else{
str = str + arr[i] + ',';
}
}
str = str + ']';
return str;
}
}
案例5:字符串反转
需求:
定义一个方法,实现字符串的反转。键盘录入一个字符串,调用该方法后,在控制台输出结果。例如:键盘录入abc,输出结果cba
思路:
1 键盘录入一个字符串
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
2 方法实现字符串的反转
3 遍历字符串的每个字符,再重新拼接成一个新的字符串
String sNew = "";
for(int i = s.length-1;i>=0;i++){
sNew = sNew + s.charAt(i);
}
System.out.println(sNew);
// 113-StringTest5
//字符串反转
public class StringTest5 {
public static void main(String[] args){
//键盘输入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String str = sc.nextLine();
//调用方法,用String变量接收
String str2 = reverseString(str);
//输出反转后的字符串
System.out.println("反转后的字符串:" + str2);
}
//定义方法实现字符串的反转,返回值类型Sring,参数是String
//方法:字符串倒着遍历,然后拼接
public static String reverseString(String str){
String str1 = "";
for(int i = str.length() - 1; i>=0; i--){
str1 += str.charAt(i);
}
return str1;
}
}
StringBuilder
StringBuilder概述
- 引入StringBuilder的原因:
对字符串进行拼接操作,每次拼接都会构建一个新的String对象,既耗时又浪费内存空间,而字符串拼接操作还无法避免。
下述这种情况,会在内存中产生多个字符串,浪费存储空间。
int[] array = {1,2,3,4,5,6};
String s = "";
for(int i =0 ;i < array.length ; i++)
{
s = s + array[i];
}
这种情况中,每次拼接字符串,都会开辟新的存储空间,
也就是说,内存空间存储的是:
“”
1
12
123
这样的形式。
- 解决方式是:
通过java提供的StringBuilder类来解决这个问题。 - 介绍:
StringBuilder是一个可变的字符串类,可以把它看成一个容器;
可变=StringBuilder对象中的内容是可变的。 - String和StringBuilder的区别:
String | StringBuilder |
---|---|
内容是不可变的 | 内容是可变的 |
StringBuilder的构造方法
方法名 | 说明 |
---|---|
public StringBuilder() | 创建一个空白可变的字符串对象,不含有任何内容 |
public StringBuilder(String str) | 根据字符串的内容,创建可变的字符串对象 |
案例:
// 117-StringB1
//StringBuilder构造方法
public class StringB1 {
public static void main(String[] args) {
//使用StingBuilder()构造方法创建对象
StringBuilder sb = new StringBuilder();
System.out.println("sb:" + sb);//用于测试构造方法StringBuilder()创建的对象是否不包含任何内容
System.out.println("sb.length()"+sb.length());
//使用StringBuilder(String str)构造方法创建对象
StringBuilder sb1 = new StringBuilder("xhj");
System.out.println("sb1:" + sb1);
System.out.println("sb1.length():" + sb1.length());
}
}
StringBuilder的常用方法
方法名 | 说明 | 举例说明 |
---|---|---|
public StringBuilder append(任意类型) | 添加数据,并返回对象本身 | sb.append()》实现字符串数据的添加,直接对sb字符串内容进行修改,并返回sb |
public StringBuilder reverse() | 返回相反的字符序列 | sb.reverse()》实现字符串的反转,直接对sb字符串内容进行修改,并返回sb |
StringBuilder delete(int start,int end) | 移除此序列的字符串中的下标是start到end之间的字符 | |
StringBuilder insert(int offset,String str) | 将字符串str插入此字符串序列offset中 | |
StringBuilder replace(int start,int end,String str) | 使用给定的字符串str替换此序列的字符串中下标start到end的字符串 |
理解:
public StringBuilder append(任意类型):StringBuilder表示的是返回值的类型,之前的对象方法返回值类型写过void、int(基本数据类型)。
案例:
// 117-StringB2
//StringBuilder的添加和反转方法
public class StringB2 {
public static void main(String[] args){
//创建StringBuilder对象
StringBuilder sb = new StringBuilder();
* 调用StringBuiler的append方法,它的返回值是对象本身 = StringBuilder类型
// StringBuilder sb1 = sb.append("hello");
// System.out.println("sb:" + sb);//sb:hello
// System.out.println("sb1:" + sb1);//sb1:hello
// //说明 对象.append修改的是对象本身,返回的也是对象本身。
// System.out.println(sb == sb1);//true
// //说明 两者在栈内存存储的 堆内存地址都相同。
// sb.append("hello");
// sb.append("world");
// sb.append(100);
// System.out.println("sb:" + sb);//sb:helloworld100
//输出结果是上述添加的总和,说明添加不会覆盖原来的字符串内容,只进行拼接。
//链式编程
sb.append("hello").append("world").append(101);
System.out.println("sb:" + sb);//sb:helloworld101
//说明 对象.append的返回值是一个对象,因为只有对象才可以调用方法append
//调用StringBuilder的反转方法 reverse
sb.reverse();
System.out.println("sb:" + sb);//sb:101dlrowolleh
}
}
StringBuilder和String的相互转换
- 原因:
两者相互转换的原因是,StringBuilder有两个好用的方法append和reverse,String要想使用这两个方法就需要转换为StringBuilder类型 - 两者的相互转换:
方法 | 说明 | 举例说明 |
---|---|---|
public String toString() | 通过toString()就可以实现把StringBuilder转换为String | StringBuilder.toString()》实现StringBuilder转换String |
pubilc StringBuilder(String str) | 通过构造方法就可以实现把String转换为StringBuilder | StringBuilder类名 对象名 = new StringBuilder类名(string对象) |
案例
案例1:String和StringBuilder的相互转换
// 117-StringB3
//StringBuilder和String的相互转换
public class StringB3 {
public static void main(String[] args){
// StringBuilder->String
System.out.println("StringBuilder->String");
StringBuilder sb = new StringBuilder();
sb.append("hello");
// String s = sb;//错误
String s = sb.toString();
System.out.println(s);//hello
System.out.println("-------------");
System.out.println("String->StringBuilder");
String s1 = "world";
// StringBuilder sb1 = s1;//错误
StringBuilder sb1 = new StringBuilder(s1);
System.out.println(sb1);//world
}
}
案例2:拼接字符串
需求:定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果。例如:数组为int[] = {1,2,3};,执行方法后的输出结果为:[1,2,3]
思路:
1 创建int类型数组
int[] arr = {1,2,3};
2 遍历数组,拼接成字符串
3 通过字符串创建StringBuilder对象
StringBuilder sb = new StringBuilder();
4 使用StringBuilder对象的方法append进行图片拼接
sb.append("[");
for(int i = 0 ; i<arr.length;i++){
if(i != arr.length-1){
sb.append(arr[i]).append(",");
}else{
sb.append(arr[i]);
}
sb.append("]");
5 使用toString方法实现StringBuilder对象 =》 String对象的转换
String s = sb.toString();
// 117-StringB4
//拼接字符串
public class StringB4 {
public static void main(String[] args){
//需求:定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果。例如:数组为int[] = {1,2,3};,执行方法后的输出结果为:[1,2,3]
//静态初始化方式定义数组
int[] arr = {1,2,3};
//调用方法,用一个变量接收
String str = addArray(arr);
System.out.println(str);
}
//定义一个方法实现int类型数组按照指定要求拼接成字符串
//返回值是String类型,参数是int[] arr
//方法定义不写static会报错,而且调用的时候会画红线。****
public static String addArray(int[] arr){
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i<arr.length;i++){
if(i == arr.length - 1){
sb.append(arr[i]);
}else{
sb.append(arr[i]).append(", ");
}
}
sb.append("]");
String s = sb.toString();
return s;
}
}
案例3:字符串反转
需求:定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果。例如:键盘录入abc,输出结果cba
思路:
1 定义一个字符串
String s = "abc";
2 创建StringBuilder对象
StringBuilder sb = new StringBuilder(s);
3 使用reverse方法实现反转
sb.reverse();
4 使用toString方法实现StringBuilder对象 =》 String对象
String sNew = sb.toString();
// 117-StringB5
//字符串反转
public class StringB5 {
public static void main(String[] args){
//需求:定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果。例如:键盘录入abc,输出结果cba
//键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.nextLine();
//调用方法,用一个变量接收结果
String str1 = strReverse(str);
//输出结果
System.out.println("字符串:" + str);
System.out.println("反转结果:" + str1);
}
//定义方法
public static String strReverse(String s){
// String类型转StringBuilder类型
StringBuilder sb = new StringBuilder(s);
// 使用reverse方法实现字符串反转
sb.reverse();
//StringBuilder转String类型
String s1 = sb.toString();
return s1;
//上述几行代码和下面这行代码是等价的。
// return new StringBuilder(s).reverse().toString();
}
}
StringBuffer
概述
StringBuffer又称为可变字符序列,类似于String的字符串缓冲区,通过某些方法调用可以改变该序列的长度和内容。
StringBuffer是个字符串缓冲区,是一个容器,可以装很多字符串,能够对其中的字符串进行各种操作。
StringBuffer的常用方法
方法名 | 说明 |
---|---|
StringBuffer append(String str) | 将指定字符串str追加到此字符串 |
StringBuffer delete(int start,int end) | 移除此序列的字符串中的下标是start到end之间的字符 |
StringBuffer insert(int offset,String str) | 将字符串str插入此字符串序列offset中 |
StringBuffer replace(int start,int end,String str) | 使用给定的字符串str替换此序列的字符串中下标start到end的字符串 |
StringBuffer reverse() | 将此字符串序列用其反转形式取代 |
String toString() | 返回此序列中数据的字符串表示形式 |
案例:
// 117-StringBufferDemo
public class StringBufferDemo {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
// 方法名:append delete insert replace reverse toString
sb.append("you are my pretty sunshine");
System.out.println(sb.toString());
// you are my pretty sunshine
sb.delete(0, 3);
System.out.println(sb.toString());
// are my pretty sunshine
sb.insert(8, "xx");
System.out.println(sb.toString());
// are my xxpretty sunshine
sb.replace(3, 5, "qq");
System.out.println(sb.toString());
// arqqmy xxpretty sunshine
sb.reverse();
System.out.println(sb.toString());
// enihsnus ytterpxx ymqqra
}
}
java内存分配详解
- java程序运行在JVM上,因此java的内存分配是在JVM中进行的。
- JVM是内存分配的前提和基础,java程序的运行会涉及以下的内存区域:
内存区名 | 说明 |
---|---|
寄存器 | JVM内部虚拟寄存器,存取速度很快,程序不可控制 |
栈 | 存放基本数据类型和对象的引用,对象存在放堆内存中 |
堆 | 存放new出来的对象,存储的只是对象的成员变量,不包括成员方法 |
静态域 方法区 静态区 | 存放static修饰的静态成员 |
常量池 | 存放常量,比如基本类型的包装类(Integer、Short、Character、Long等)和String,常量池在堆内存中 |
非RAM存储 | 硬盘等永久存储空间 |
注意:
- 静态域、堆内存被所有线程共享;
- 静态域包含所有的class和static变量,即包含的是这个程序中永远唯一的元素;