JVM内存分配及String类的常用方法解析
创始人
2024-12-22 12:02:17
0次

一,JVM内存分配和常量池

区域名称的说明:

1.1,方法区:

属于数据共享内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

1.2,虚拟机栈

虚拟机栈就是我们通常说的栈,是Java执行方法的内存模型,每当执行一次方法时,都会创建一个栈帧。把栈帧压入栈,当Java方法调用时返回正常的结果或者捕获异常时,栈帧出栈。

栈帧:栈帧存储方法的相关信息,包含局部变量数表、返回值、操作数栈、动态链接。

1.3,本地方法栈

从功能上来说与虚拟机栈类似,但是虚拟机栈执行的是字节码,而本地方法栈调用的是Native方法,并且它是线程独享的。

1.4,程序计数器

程序计数器是线程独享的,它是记录当前线程执行的字节码行号。在多线程执行时,CPU会来回在线程之间进行切换,那么当再次回到一条线程时,是如何得知线程的存储单元及执行指令。而程序计数器便会进行存储下一条存储单元的地址,执行完毕后程序计数器自动加 1 ,以此循环直到程序结束为止。

1.5,堆

说到堆这个概念想必都不陌生,它是内存中的重要角色。它主要是用来存储被创建出来的对象,通过关键字new实例出来的,是所有线程共享的一块最大的区域。

==特别注意:在JDK1.7及以后,常量池移动到堆内存中。==

堆还包括一个==常量池==,用来存储编译期间生成的==字面量和符号==引用。这部分内容在类被加载后,都会存储到方法区中。同时,运行时产生的新常量也可以被放入常量池中,比如 String 类中的 intern() 方法产生的常量。

常量池就是这个类型用到的常量的一个有序集合。包括直接常量(基本类型,String)和对其他类型、方法、字段的符号引用。

二,常量池

2.1,什么是常量:

常量是指被final修饰的变量,值一旦确定就无法改变。

final可以修饰静态变量、方法、实例变量和局部变量。

常量池分为两种形式:静态常量池和运行时常量池

2.2,静态常量池

即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分空间。这种常量池用于存放字面量和符号引用量。

2.3,运行时常量池

指JVM虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。同样运行时常量池一个重要的特征就是具有动态性,指并不需要常量只有在编译期才会产生,在运行期也会将新的常量保存到常量池中,如String类中的intern()方法。

三,== 和equals

3.1,两者之间区边

==:

对于基本类型来说:==表示数值的比较

对于引用类型来说:==表示地址值的比较

equals:

比较的是两者之间值是否相等,但是Java中的类都是直接或者间接继承Object类,而equals不也例外。其实在equals源码中也是使用==进行比较的,如下源码:

![](https://img2018.cnblogs.com/blog/1655301/201909/1655301-20190902223856542-1095893842.png)

那么问题来了,这和==又有什么区别呢?

上面说到equals也是继承自java.lang.Object,因此可以对equals进行重写来定义我们自己的比较方式。

请参看以下代码:

String str1 = "abc"; String str2 = "abc"; char[] strArray = {'a','b','c'}; String str3 = new String(strArray); String str4 = "abc"; System.out.println(str1 == str2);  System.out.println(str1 == str3);  System.out.println(str2 == str3);  System.out.println(str4.equals(str1));

以上运行结果为:

truefalsefalsetrue

接下来我们依次分析上面的结果:

1,str1与str2比较的是字符串对象地址,因为它们的值是相同的,所以地址值也是相同的。

2,str3是new出来的示例对象,在堆内存中会开辟一块新的内存地址,它并不在常量池中。所以返回结果为false。

3,同理str2与str3比较也是一样的结果。

4,equals比较的是值是否相同,所以返回的结果为true。

如图所示:

四,String常用方法

首先声明字符串:

String str1 = "abc";

4.1,int length()

int length = str1.length(); System.out.println(length);

4.2,char charAt(值)

String str= "abc";char c = str.charAt(1); System.out.println(c);

4.3,char toCharArray()

String str= "abc";char c[] = str.toCharArray(); for (int i = 0; i < c.length; i++) { System.out.println("转为数组输出:" + c[i]);}

4.4,int indexOf("字符"); int lastIndexOf("字符")

String str="axcdefgabc";int a1 = str.indexOf("a"); int a2 = str.indexOf("x", 2);int a3 = str.lastIndexOf("c"); System.out.println("你的位置为:" + a1); System.out.println("为的位置为:" + a2);System.out.println("点最后出现的位置为:" + a3);

4.5,字符串大小写转换

toUpperCase(); 转换成大写 toLowerCase();转换成小写

String str = "hello world";String str1 = "HELLO WORD";System.out.println("将字符串转大写为:" + str.toUpperCase());System.out.println("将字符串转换成小写为:" + str1.toLowerCase());

4.6,String[] split("字符")

String str = "abc,def,123";String[] arr1 = str.split(",");

4.7,boolean equals(Object anObject)

String str = "abc"; String str1= "123";  if(str.equals(str1)) {  System.out.println("相等");  }  else{ System.out.println("不相等");  }

4.8,String trim()

String str = " abc "; System.out.println("去掉左右空格后:" + str.trim());

4.9,字符串替换

String replace(char oldChar,char newChar) String replaceAll(String,String)将某个内容全部替换成指定内容

String repalceFirst(String,String)将第一次出现的某个内容替换成指定的内容

String str = "abcdefgabdc"; System.out.println("替换:" + str.replace("abc", "123")); System.out.println("替换全部:" + str.replaceAll("ab", "12")); System.out.println("替换第一次出现:" + str.repalceFirst("a", "a"));

4.10,String substring(int beginIndex,int endIndex)

String str = "abcdefg";  // 截取0-3个位置的内容, 不含3  System.out.println("截取后的字符为:" + str.substring(0, 3)); // 从第3个位置开始截取, 含2 System.out.println("截取后字符为:" + str.substring(2));

4.11,boolean equalsIgnoreCase(String)

String str = "ABC";String str1 = "abc";if(str.equalsIgnoreCase(str1)){ System.out.println("相等");}else{ System.out.println("不相等");}

4.12,boolean contains(String)

String str = "ABCDEF";String str1 = "ABC";if(str.contains(str1)){ System.out.println("str内容中包含ABC");}else{ System.out.println("str内容中不包含ABC");}

五,总结

1,对于JVM内存的分配,在jdk6中存在方法区,jdk8中便没有方法区,改成元区域。

2,jdk6中常量池存在方法区中,jdk7以后常量池移动到堆中。

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...