Java学习day12:static关键字,字符串声明,字符串常量池

声明:该专栏本人重新过一遍java知识点时候的笔记汇总,主要是每天的知识点+题解,算是让自己巩固复习,也希望能给初学的朋友们一点帮助,大佬们不喜勿喷(抱拳了老铁!)


 往期回顾:

Java学习day11:异常-CSDN博客

Java学习day10:多态、向下转型、instanceof关键字-CSDN博客


Java学习day09:super、final关键字,抽象类和接口-CSDN博客

......

Java学习day12:static关键字,字符串声明,字符串常量池

一、static关键字(static:静态)

1.1生活角度来理解静态资源

公共的资源的都属于静态的东西,对象可以使用静态的资源,但是和对象无关。

比如,图书馆里的饮水机,就是一种静态资源,人这种对象可以通过水杯去接水来使用,但不能说饮水机是他的,也就是说,对象可以用静态资源,但是跟对象没关系。

1.2Java中的静态

1.2.1作用
(1)修饰成员变量,使其成为静态属性
(2)修饰成员方法,使其成为静态方法
(3)修饰代码块,使其成为静态代码块
1.2.1.1static修饰成员变量
1.2.1.1.1语法格式:

static 数据类型  变量名;

1.2.1.1.2注意事项:

1.使用static修饰的变量叫静态变量
2.代码中对象还没有创建的时候,如果加载了类,static修饰的属性已经存在了,和对象没有关系。只和类本身有关。

1.2.1.1.3示例

首先来说大家要记住,对象是可以调用静态属性并赋值,输出的。同时标准的来说,是用类来调用,所以会发现,对象和类都可调用静态属性并赋值。

但是在输出的时候,是以最后一次赋值结果为准,不管是谁调用赋值的,所以大家可以直接认为,静态属性只有一个,所有的赋值修改都是基于这一个属性

class Person {
 String name;
 int age;
 static String country;
}
public class Demo2 {
 public static void main(String[] args) {
  Person sb = new Person();
  sb.name = "张三";
  sb.age = 23;
  Person.country = "中国";
  //The static field Person.country 
  //should be accessed in a static way
  System.out.println(sb.country);//中国
  System.out.println(Person.country);//in a static way
  sb.country = "PRC";
  System.out.println(Person.country);//PRC
 }

}
 1.2.1.1.4实际内存分析

当然,看看实际的内存分析,会发现对象调用和类调用的静态属性是在不同分区的,对象调用在堆区,而类调用是在方法区。但是,但是!赋值修改会互通。

 大家实际开发的时候,记住用类.静态属性去调用就OK。

1.2.1.2static修饰成员方法
1.2.1.2.1语法格式

public static 返回值 方法的名字 (参数列表) {}
调用静态方法:类.方法名字();

1.2.1.2.2示例
class Dog {
 public void eat () {
  System.out.println("普通的成员方法");
 }
 public static void sleep () {
  System.out.println("睡吧不用看家了");
 }
}
public class Demo3 {
 public static void main(String[] args) {
  Dog.sleep();
  //Dog.eat();只能拿对象来调用这个方法eat
  Demo3.test();
 }
 public static void test () {
  System.out.println("嘻嘻");
 }

}

这里需要注意的,只能用类调用静态方法,也只能用对象调用普通方法,如果方法写在main主函数里,就用主类名直接调用,而且还可以省略主类名 

 虽然在某些情况下,Java 编译器可能允许使用对象来调用静态方法或使用类名来调用普通方法,但这并不代表这样做是推荐的或是符合最佳实践的。建议在编写代码时,尽量遵循通用的编程规范和最佳实践。

1.2.1.3static修饰代码块
1.2.1.3.1语法格式

static {
 语句体
}

只要这个类加载,那么静态代码块一定会执行

执行顺序:  静态代码块-->构造代码块-->构造方法

1.2.1.3.2示例1
class Cat {
 public Cat () {
  System.out.println("无参构造方法");
 }
 {
  System.out.println("构造代码块");
 }
 static {
  System.out.println("静态的代码块");
 }
}
public class Demo4 {
 public static void main(String[] args) {
  Cat cat = new Cat();
 }

}

 最后输出结果验证执行顺序

再次强调,修饰成静态的方法、属性、代码块都跟对象无关,而只跟类有关

所以可以在示例里看到,调用的时候,需要用类名.静态属性/静态方法/静态代码块

同时注意最后的结果,静态代码块会先执行,这个在开发中会用到的

1.2.1.3.3示例2
package com.qfedu.a_static;

class Man {
 static String name;//静态的属性  和对象无关的
 //静态方法
 public static void eat () {
  System.out.println("吃饭喝酒");
 }
 //静态代码块
 static {
  System.out.println("嘻嘻");
 }
}
public class Demo1 {
 public static void main(String[] args) {
  //咋使用 类.静态的属性
  Man.name = "狗蛋";
  System.out.println(Man.name);
  //使用  类.静态方法名字()
  Man.eat();
  
 }

}

二、字符串声明

 先强调一个知识点:

== 比较的是内存地址
equal比较的是地址,如果地址不一样 再去比较内容。如果内容一样就是true
开发中字符串的比较使用的是equals

2.1直接声明 

对象创建在栈区

栈区如果对象内容一致,则是同一个内存地址,用==号比较时,结果为true

2.2创建string对象

对象创建在堆区

2.3内存分析

这里堆区的字符串常量池可能大家有点懵,没事的,马上就讲。

三、字符串常量池 

3.1为什么要有字符串常量池

首先对象的分配要付出时间和空间上的开销,字符串可以说是和 8 个基本类型一样常用的类型,甚至比 8 个基本类型更加常用,故而频繁的创建字符串对象,对性能的影响是非常大的,所以,用常量池的方式可以很大程度上降低对象创建、分配的次数,从而提升性能。

3.2字符串赋值方式 

这部分知识点有点绕,希望大家尽量理解。

同时声明,这段知识点来自以下博文,大家更可以看看原文,写得很好。

90%的同学都没搞清楚的 Java 字符串常量池问题(图文并茂) - 古时的风筝的个人空间 - OSCHINA - 中文开源技术交流社区

3.2.1字面量赋值

如String s1 = "古时的风筝"

这种方式叫做字面量声明,也就用把字符串用双引号引起来,然后赋值给一个变量。

这种情况下会直接将字符串放到字符串常量池中,然后返回给变量。

此时再声明一个内容相同的字符串,会发现字符串常量池中已经存在了,那直接指向常量池中的地址即可。

所以 s1== s2 的结果是 true。

3.2.2new String () 方式

基本上不建议这么用,除非有特殊的逻辑需要。
String a = "古时的";
String s2 = new String(a + "风筝");

此时需要考虑的情况:

1.字符串常量池之前已经存在相同字符串
比如在使用new之前,已经用字面量声明的方式声明了一个变量,此时字符串常量池中已经存在了相同内容的字符串常量。 

1.首先会在堆中创建一个 s2 变量的对象引用;
2.然后将这个对象引用指向字符串常量池中的已经存在的常量;

2.字符串常量池中不存在相同内容的常量
之前没有任何地方用到了这个字符串,第一次声明这个字符串就用的是 new String () 的方式,这种情况下会直接在堆中创建一个字符串对象然后返回给变量。

 new String () 不管常量池中有没有,都会在堆中新建一个对象,新建出来的对象,当然不会和其他对象相等。

3.2.3intern () 池化

好多地方说,如果字符串常量池中不存在的话,就先把字符串先放进去,然后再引用字符串常量池的这个常量对象,这种说法是有问题的,只是 new String()的话,如果池中没有也不会放一份进去。那什么时候会放到字符串常量池呢,就是在使用intern()方法之后。

intern()的定义:如果当前字符串内容存在于字符串常量池,存在的条件是使用equas()方法为ture,也就是内容是一样的,那直接返回此字符串在常量池的引用;如果之前不在字符串常量池中,那么在常量池创建一个引用并且指向堆中已存在的字符串,然后返回常量池中的地址。

还是考虑两种情况:

 1.准备池化的字符串与字符串常量池中的字符串有相同 (equas () 判断)

此时s1 == s2 会返回 fasle。然后我们调用 s2 = s2.intern (),将池化操作返回的结果赋值给 s2,就会发生如下的变化。

2.字符串常量池中不存在相同内容的字符串

使用了 intern () 之后发生了什么呢,在常量池新增了一个对象,但是 并没有将字符串复制一份到常量池,而是直接指向了之前已经存在于堆中的字符串对象。因为在JDK1.7之后,字符串常量池不一定就是存字符串对象的,还有可能存储的是一个指向堆中地址的引用,现在说的就是这种情况,注意了,下图是只调用了s2.intern(),并没有返回给一个变量。其中字符串常量池(0x88)指向堆中字符串对象(0x99)就是intern()的过程。

注意此时只是调用了intern()池化函数,没有赋值给s2,所以此时s2没有指向字符串常量池

        只有当我们把 s2.intern () 的结果返回给 s2 时,s2 才真正的指向字符串常量池。

3.2.4示例

综上,我们通过一个示例体会,你是否能准确讲述出每个对比结果的原因?

public class Test {

    public static void main(String[] args) {
        String s1 = "古时的风筝";
        String s2 = "古时的风筝";
        String a = "古时的";
      
        String s3 = new String(a + "风筝");
        String s4 = new String(a + "风筝");
        System.out.println(s1 == s2); // 【1】 true
        System.out.println(s2 == s3); // 【2】 false
        System.out.println(s3 == s4); // 【3】 false
        s3.intern();
        System.out.println(s2 == s3); // 【4】 false
        s3 = s3.intern();
        System.out.println(s2 == s3); // 【5】 true
        s4 = s4.intern();
        System.out.println(s3 == s4); // 【6】 true
    }
}

 如果大家都能准确说出每个结果的原因,那基本就没什么问题了。

如果不能,那就再多看几遍。

【1】:s1 == s2 返回 ture,因为都是字面量声明,全都指向字符串常量池中同一字符串。

【2】: s2 == s3 返回 false,因为 new String () 是在堆中新建对象,所以和常量池的常量不相同。

【3】: s3 == s4 返回 false,都是在堆中新建对象,所以是两个对象,肯定不相同。

【4】: s2 == s3 返回 false,前面虽然调用了 intern () ,但是没有返回,不起作用。

【5】: s2 == s3 返回 ture,前面调用了 intern () ,并且返回给了 s3 ,此时 s2、s3 都直接指向常量池的同一个字符串。

【6】: s3 == s4 返回 true,和 s3 相同,都指向了常量池同一个字符串。

 以上,就是今天的所有知识点了。字符串常量池的问题有点绕,但是不难,大家静下心慢慢看,慢慢理解,不是什么大问题。

加油吧,预祝大家变得更强!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/151660.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

错误:CUDA error: device-side assert triggered CUDA kernel errors

对llama扩充中文词表后直接增量预训练,忘记设置--modules_to_save embed_tokens,lm_head,所以导致向量维度不一致,出现下面的错误。 1. 错误 2. 原因 出现这个错误的原因可能是因为维度或标签不一致。可以仔细排查一下。

【k8s集群搭建(二):基于虚拟机的linux的k8s集群搭建_超详细_可视化界面Dashboard安装_记录全过程踩坑记录及解决方法】

在 master 执行 # 根据 在线配置文件 创建资源 kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml设置访问端口 # 修改配置文件 找到 type,将 ClusterIP 改成 NodePort kubectl edit svc kubernetes-…

虾皮之家数据分析插件:知虾数据分析工具提升销量的利器

在当今的电商市场中,虾皮Shopee成为了许多商家的首选平台。然而,随着竞争的加剧,店铺运营变得越来越具有挑战性。如何提升销量,优化标题和图片,合理设置SKU,并准确跟踪店铺活动数据和竞品数据,已…

为什么网安人才缺口那么大,就业率却上不去?

为什么网安相关行业人才缺口还有三百多万,但现在却还有很多程序员找不到工作,难道我们又被所谓大数据骗了吗? 其实啊,造成如此现象的有以下几点原因:首先,教学青黄不接,因为网安属于近几年新开…

SCons

什么是构建工具(系统) 构建工具(software construction tool)是一种软件,它可以**根据一定的规则或指令,将源代码编译成可执行的二进制程序。**这是构建工具最基本也最重要的功能。 实际上构建工具的功能…

03.智慧商城——路由配置

01. 路由配置 - 一级路由 但凡是单个页面,独立展示的,都是一级路由 路由设计: 登录页首页架子 首页 - 二级分类页 - 二级购物车 - 二级我的 - 二级 搜索页搜索列表页商品详情页结算支付页我的订单页 router/index.js 配置一级路由&#x…

基于springboot实现一起来约苗管理系统项目【项目源码】

基于springboot实现一起来约苗平台管理系统演示 Java技术 Java是由Sun公司推出的一门跨平台的面向对象的程序设计语言。因为Java 技术具有卓越的通用性、高效性、健壮的安全性和平台移植性的特点,而且Java是开源的,拥有全世界最大的开发者专业社群&…

Hack_Kid

Hack_Kid 靶机地址:https://download.vulnhub.com/hackerkid/Hacker_Kid-v1.0.1.ova 一、主机发现 发现靶机IP为192.168.80.135 二、端口扫描 发现靶机开启了80、53、9999端口 三、信息收集 1.访问80端口 2.访问9999端口 根据靶场作者的提示,不…

未来服务器操作系统的趋势与展望

摘要: 随着云计算、大数据和人工智能不断的发展,服务器操作系统也需要随之进行新一轮的升级。本文通过分析当前服务器操作系统的现状,探讨了未来服务器操作系统的趋势和展望,并针对一些关键问题提出了解决方案。 一、引言 服务器…

老哥们平日是怎么排查线上问题的?

1、做好监控告警 如果线上出现了问题,我们更多的是希望由监控告警发现我们出了线上问题,而不是等到业务侧反馈。所以,我们需要对核心接口做好监控告警的功能。 2、定位报警层面 如果是业务代码层面的监控报警,那我们应该是可以…

PVE Win平台虚拟机下如何安装恢复自定义备份Win系统镜像ISO文件(已成功实现)

环境: Virtual Environment 7.3-3 Win s2019 UltraISO9.7 USM6.0 NTLite_v2.1.1.7917 问题描述: PVE Win平台虚拟机下如何安装恢复自定义备份Win系统镜像ISO文件 本次目标 主要是对虚拟机里面Win系统备份做成可安装ISO文件恢复至别的虚拟机或者实体机上 解决方案: …

海康Visionmaster-环境配置:MFC 二次开发环境配置方法

1 新建 MFC 工程,拷贝 DLL:VM\VisionMaster4.0.0\Development\V4.0.0 \ComControl\bin\x64 下的所有拷贝到项目工程输出目录下,如下图所示,项目的输出路径是 Dll 文件夹。 2 通过配置 C目录和链接器的方式配置 VM 环境 2.1 C目录下添加附加…

金蝶云星空单据体启用块粘贴

文章目录 金蝶云星空单据体启用块粘贴 金蝶云星空单据体启用块粘贴

c/c++语言算法技巧汇总大复习2

标题前面打*号的为多数考纲范围外的,可以选择性查看 🔗链接:严书代码大全 🔗链接:c/c语言算法技巧汇总大复习1 🔗链接:c/c语言算法技巧汇总大复习2 目录 Dp动态规划入门练习 青蛙跳台阶练习&…

大数据Hadoop之——部署hadoop+hive+Mysql环境(Linux)

目录 一、JDK的安装 1、安装jdk 2、配置Java环境变量 3、加载环境变量 4、进行校验 二、hadoop的集群搭建 1、hadoop的下载安装 2、配置文件设置 2.1. 配置 hadoop-env.sh 2.2. 配置 core-site.xml 2.3. 配置hdfs-site.xml 2.4. 配置 yarn-site.xml 2.5. 配置 ma…

韦东山linux驱动开发学习【常更】

1.linux目录简单介绍 2.直接运行需要在$path路径下

YOLOv7独家原创改进:最新原创WIoU_NMS改进点,改进有效可以直接当做自己的原创改进点来写,提升网络模型性能精度

💡该教程为属于《芒果书》📚系列,包含大量的原创首发改进方式, 所有文章都是全网首发原创改进内容🚀 💡本篇文章为YOLOv7独家原创改进:独家首发最新原创WIoU_NMS改进点,改进有效可以直接当做自己的原创改进点来写,提升网络模型性能精度。 💡对自己数据集改进有效…

AI大模型创意赛秘籍:3要素搞定初赛提交,3步走开发一个网站!

11月10日,飞桨星河社区X智海Mo平台,AI大模型创意应用大赛的首场培训圆满结束!培训过程中的完整网站代码案例,可在报名比赛后获取。 初赛:1码2表3图,快速搞定初赛提交 培训实践营上,Jungle老师分…

BUUCTF 九连环 1

BUUCTF:https://buuoj.cn/challenges 题目描述: 下载附件,解压得到一张.jpg图片。 密文: 解题思路: 1、一张图片,典型的图片隐写。放到Kali中,使用binwalk检测,确认图片中隐藏zip压缩包。 使…

docker 部署日志平台出错汇总

第一次运行elasticsearch:8.11.1镜像,报错如下: [rootmaster ~]# docker run --name es03 --net elastic -p 9200:9200 -it -m 1GB docker.elastic.co/elasticsearch/elasticsearch:8.11.1 docker: Error response from daemon: driver failed programmi…