前言
今天就讲了一些很基本的东西,例如基本运算符,但是关于字符串的知识可以拓展到封装类、常量池,所以今天的博客总结一下相关知识。
什么是常量池
在Java的实体书(例如零基础Java从入门到入土)里,在最开始讲常量那一章的时候,会提到一个“常量池”,但是所提非常浅显,甚至讲不清楚是个啥。
简单地讲,常量池就是放了一些你很常用的东西,为了方便你随取随用的池子。
那么,常量池 什么时候“建立”,里面都具体有什么,一段程序运行时会有几个常量池呢?
首先,常量池又叫"Class常量池",在后缀为“.java”的文件被编译为“.class”后,被Java虚拟机加载进来时产生的。
Class文件包含了类的版本、字段、方法、接口等信息,以及常量池。
版本和字段不是我们现阶段的学习目标,我们要关注的主要是后面这些。
那么常量池里具体有什么呢?
常量池的内容,大致包括两类——字面量、符号引用。
字面量
字面量有三类,文本字符串 、被声明为final的常量值、基本数据类型的值。
其中文本字符串指的是"abc"这种东西,其余两种应该是很显而易见的东西,不加赘述。
符号引用
符号引用,这个概念我也是查阅了很多资料,才梳理出来,毕竟像我这种初学者也在整理博客,网上不懂装懂的人太多了,实在是不能直接以哪一篇作为准绳。
我们先看一段代码
import java.util.Scanner;
public class Learning3 {
public static void main(String[] args) {
byte a = 100;
String s = String.valueOf(a);
Integer b = Integer.valueOf(s);
int c = Integer.parseInt(s);
double d = (double) c;
System.out.println(s);
shuChu();
niHao();
People();
}
public static void shuChu() {
System.out.println("Welcome to java");
System.out.print("Welcome to computer science,");
System.out.println("programming is fun");
}
public static void niHao() {
Scanner sc = new Scanner(System.in);
String mingZi = sc.nextLine();
System.out.println("hello ," + mingZi);
}
public static void People() {
People a = new People();
a.setMing("三");
a.setXing("张");
a.setAge(19);
a.setAddress("China");
System.out.println(a.getAge() + "岁的" + a.getXing() + a.getMing() + "住在" + a.getAddress());
}
}
import java.security.PublicKey;
public class People {
private String Xing;
private String Ming;
private int age;
private String address;
public People(String xing, String ming, int age, String address) {
Xing = xing;
Ming = ming;
this.age = age;
this.address = address;
}
public People() {
}
public void setXing(String xing) {
Xing = xing;
}
public void setMing(String ming) {
Ming = ming;
}
public void setAge(int age) {
this.age = age;
}
public void setAddress(String address) {
this.address = address;
}
public String getXing() {
return Xing;
}
public String getMing() {
return Ming;
}
public int getAge() {
return age;
}
public String getAddress() {
return address;
}
}
我们可以看到,我们在Learning3这个类中引用了People类,在编译的时候Learning3类并不知道People类的实际地址,只知道一个类似CONSTANT_Class_info的“符号”,用常量池的这个符号表示People类的地址。
String
在过去学的C语言中,可能字符串这一种类型,和字符等没什么使用上的区别,但是在Java中,是有明显区别的。
首先,第二天的总结内,讲过了封装类相关的知识,这里不再赘述。
String——字符串,不是一种基本数据类型而是封装类,即它和字符、整型、浮点型等有本质区别。
举个例子,基本数据类型的"=="表示比较数值,而封装类表示比较地址。
我们既然讲字符串那么还是拿String为例
看一段代码
String S = new String("Hei");
这一段代码被编译成class文件时发生了什么?
我们表面上看,是new了一个对象S,它的值是"Hei",那么实际上呢?
实际上,在编译运行时,这个语句new出了两个对象,一个在堆内存中,一个在常量池里。
比如运行时的栈内存存储着String S 0x001,堆内存中就会出现一个0x001,然后常量池出现一个0x001 “Hei”。
但是我们写String I1 = “Hei” ;时并不是这样的,这样申明一个String变量,只会在常量池里面生成一个0x002 “Hei”; 而且我们之后再将"Hei"通过这种赋值方式赋值时,再编译时,是直接从常量池里面取出这个值的地址,使得别的新变量名指向这个地址。
因此我们看下面这个
就不难理解了