暑期集训第三天

本文详细介绍了Java中的常量池,包括其在.class文件中的作用,以及字面量和符号引用的概念。此外,还探讨了String对象的创建和内存分配,特别是`new String()`与直接赋值的不同。通过示例代码解释了String对象在内存中的表现,强调了字符串常量池的特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

今天就讲了一些很基本的东西,例如基本运算符,但是关于字符串的知识可以拓展到封装类、常量池,所以今天的博客总结一下相关知识。

什么是常量池

在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"通过这种赋值方式赋值时,再编译时,是直接从常量池里面取出这个值的地址,使得别的新变量名指向这个地址。
因此我们看下面这个
在这里插入图片描述

就不难理解了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值