当前位置: 首页 > news >正文

Java基础扫盲(二)

想看Java基础扫盲(一)的可以观看我的上篇文章Java基础扫盲

目录

String为什么设计为不可变的

String有长度限制吗

为什么JDK9将String的char[]改为byte[]

泛型中K,T,V,E,Object,?等都代表什么含义 

怎么修改一个类中使用了private修饰的String类型的变量

1. 使用 Setter 方法

2. 使用反射


String为什么设计为不可变的

关于String为什么设计为不可变的,可以从缓存、安全性、线程安全和性能等角度出发的。

缓存

字符串是使用最广泛的数据结构。大量的字符串的创建是非常耗费资源的,所以,Java提供了对字符串的缓存功能,可以大大的节省堆空间。

JVM中专门开辟了一部分空间来存储Java字符串,那就是字符串池。

通过字符串池,两个内容相同的字符串变量,可以从池中指向同一个字符串对象,从而节省了关键的内存资源

String s = "abcd";
String s2 = s;

对于这个例子,s和s2都表示"abcd",所以他们会指向字符串池中的同一个字符串对象:

但是,之所以可以这么做,主要是因为字符串的不变性,如果字符串是可变的,我们一旦修改了s的内容,那必然导致s2的内容也被动的改变了。

hashcode缓存

由于字符串对象被广泛地用作数据结构,它们也被广泛地用于哈希实现,如HashMap、HashTable、HashSet等。在对这些散列实现进行操作时,经常调用hashCode()方法。

不可变性保证了字符串的值不会改变。因此,hashCode()方法在String类中被重写,以方便缓存,这样在第一次hashCode()调用期间计算和缓存散列,并从那时起返回相同的值。

安全性:

字符串在Java应用程序中广泛用于存储敏感信息,如用户名、密码、连接url、网络连接等。JVM类加载器在加载类的时也广泛地使用它。

因此,保护String类对于提升整个应用程序的安全性至关重要。

当我们在程序中传递一个字符串的时候,如果这个字符串的内容是不可变的,那么我们就可以相信这个字符串中的内容。

但是,如果是可变的,那么这个字符串内容就可能随时都被修改。那么这个字符串内容就完全不可信了。这样整个系统就没有安全性可言了。

线程安全性:

不可变会自动使字符串成为线程安全的,因为当从多个线程访问它们时,它们不会被更改。

因此,一般来说,不可变对象可以在同时运行的多个线程之间共享。它们也是线程安全的,因为如果线程更改了值,那么将在字符串池中创建一个新的字符串,而不是修改相同的值。因此,字符串对于多线程来说是安全的。

性能:

字符串池、hashcode缓存等,都是提升性能的体现。

因为字符串不可变,所以可以用字符串池缓存,可以大大节省堆内存。而且还可以提前对hashcode进行缓存,更加高效

由于字符串是应用最广泛的数据结构,提高字符串的性能对提高整个应用程序的总体性能有相当大的影响。

String有长度限制吗

String时有长度限制的,编译期和运行期不一样。

编译期需要用CONSTANT_Utf8_info 结构用于表示字符串常量的值,而这个结构是有长度限制,他的限制是65535

运行期,String的length参数是Int类型的,那么也就是说,String定义的时候,最大支持的长度就是int的最大范围值。根据Integer类的定义,java.lang.Integer#MAX_VALUE的最大值是2^31 - 1;

常量池限制:

javac是将Java文件编译成class文件的一个命令,那么在Class文件生成过程中,就需要遵守一定的格式。

根据《Java虚拟机规范》中常量池的定义,CONSTANT_String_info 用于表示 java.lang.String 类型的常量对象,格式如下:

CONSTANT_String_info {u1 tag;u2 string_index;
}

其中,string_index 项的值必须是对常量池的有效索引, 常量池在该索引处的项必须是 CONSTANT_Utf8_info 结构,表示一组 Unicode 码点序列,这组 Unicode 码点序列最终会被初始化为一个 String 对象。CONSTANT_Utf8_info 结构用于表示字符串常量的值:

CONSTANT_Utf8_info {u1 tag;u2 length;u1 bytes[length];
}

其中,length则指明了 bytes[]数组的长度,其类型为u2,u2表示两个字节的无符号数,那么1个字节有8位,2个字节就有16位。16位无符号数可表示的最大值位2^16 - 1 = 65535。也就是说Class文件中常量池的格式规定了,其字符串常量的长度不能超过65535。

private void checkStringConstant(DiagnosticPosition var1, Object var2) {if (this.nerrs == 0 && var2 != null && var2 instanceof String && ((String)var2).length() >= 65535) {this.log.error(var1, "limit.string", new Object[0]);++this.nerrs;}
}

代码中可以看出,当参数类型为String,并且长度大于等于65535的时候,就会导致编译失败。

运行期限制:

上面提到的这种String长度的限制是编译期的限制,也就是使用String s= “”;这种字面值方式定义的时候才会有的限制。String类中有很多重载的构造函数,其中有几个是支持用户传入length来执行长度的:

public String(byte bytes[], int offset, int length)

这里面的参数length是使用int类型定义的,那么也就是说,String定义的时候,最大支持的长度就是int的最大范围值。根据Integer类的定义,java.lang.Integer#MAX_VALUE的最大值是2^31 - 1;这个值约等于4G,在运行期,如果String的长度超过这个范围,就可能会抛出异常。(在jdk 1.9之前)。int 是一个 32 位变量类型,取正数部分来算的话,他们最长可以有

2^31-1 =2147483647 个 16-bit Unicodecharacter2147483647 * 16 = 34359738352 位
34359738352 / 8 = 4294967294 (Byte)
4294967294 / 1024 = 4194303.998046875 (KB)
4194303.998046875 / 1024 = 4095.9999980926513671875 (MB)
4095.9999980926513671875 / 1024 = 3.99999999813735485076904296875 (GB)

大约有4GB左右。

为什么JDK9将String的char[]改为byte[]

在Java 9之前,字符串内部是由字符数组char[] 来表示的。

/** The value is used for character storage. */private final char value[];

由于Java内部使用UTF-16,每个char占据两个字节,即使某些字符可以用一个字节(LATIN-1)表示,但是也仍然会占用两个字节。所以,JDK 9就对他做了优化。

Latin1(又称ISO 8859-1)是一种字符编码格式,用于表示西欧语言,包括英语、法语、德语、西班牙语、葡萄牙语、意大利语等。它由国际标准化组织(ISO)定义,并涵盖了包括ASCII在内的128个字符。 Latin1编码使用单字节编码方案,也就是说每个字符只占用一个字节,其中第一位固定为0,后面的七位可以表示128个字符。这样,Latin1编码可以很方便地与ASCII兼容。

这就是Java 9引入了"Compact String"的概念:每当我们创建一个字符串时,如果它的所有字符都可以用单个字节(Latin-1)表示,那么将会在内部使用字节数组来保存一半所需的空间,但是如果有一个字符需要超过8位来表示,Java将继续使用UTF-16与字符数组。

泛型中K,T,V,E,Object,?等都代表什么含义 

E – Element (在集合中使用,因为集合中存放的是元素)
T – Type(Java 类)
K – Key(键)
V – Value(值)
N – Number(数值类型)
? – 表示不确定的java类型(无限制通配符类型)
S、U、V – 这几个有时候也有,这些字母本身没有特定的含义,它们只是代表某种未指定的类型。一般认为和T差不多。
Object – 是所有类的根类,任何类的对象都可以设置给该Object引用变量,使用的时候可能需要类型强制转换,但是用使用了泛型T、E等这些标识符后,在实际用之前类型就已经确定了,不需要再进行类型强制转换。

示例1:使用T作为泛型类型参数,表示任何类型

// 示例1:使用T作为泛型类型参数,表示任何类型
public class MyGenericClass<T> {private T myField;public MyGenericClass(T myField) {this.myField = myField;}public T getMyField() {return myField;}
}

示例2:使用K、V作为泛型类型参数,表示键值对中的键和值的类型 

// 示例2:使用K、V作为泛型类型参数,表示键值对中的键和值的类型
public class MyMap<K, V> {private List<Entry<K, V>> entries;public MyMap() {entries = new ArrayList<>();}public void put(K key, V value) {Entry<K, V> entry = new Entry<>(key, value);entries.add(entry);}public V get(K key) {for (Entry<K, V> entry : entries) {if (entry.getKey().equals(key)) {return entry.getValue();}}return null;}private class Entry<K, V> {private K key;private V value;public Entry(K key, V value) {this.key = key;this.value = value;}public K getKey() {return key;}public V getValue() {return value;}}
}

示例3:使用E作为泛型类型参数,表示集合中的元素类型 

// 示例3:使用E作为泛型类型参数,表示集合中的元素类型
public class MyList<E> {private List<E> elements;public MyList() {elements = new ArrayList<>();}public void add(E element) {elements.add(element);}public E get(int index) {return elements.get(index);}
}

示例4:使用Object作为泛型类型参数,表示可以接受任何类型 

// 示例4:使用Object作为泛型类型参数,表示可以接受任何类型
public class MyGenericClass {private Object myField;public MyGenericClass(Object myField) {this.myField = myField;}public Object getMyField() {return myField;}
}

怎么修改一个类中使用了private修饰的String类型的变量

在Java中,String 类型确实是不可变的。这意味着一旦一个 String 对象被创建,其内容就不能被改变。任何看似修改了 String 值的操作实际上都是创建了一个新的 String 对象。

当然,如果不考虑这个可不可变的问题,新建一个也算改了的话。那么就有以下几种方式:

1、在Java中,private 访问修饰符限制了只有类本身可以访问和修改其成员变量。如果需要在类的外部修改一个 private 修饰的 String 参数,通常有几种方法:

1. 使用 Setter 方法

这是最常用且最符合对象导向设计原则的方法。在类内部提供一个公开的 setter 方法来修改 private 变量的值。

public class MyClass {private String myString;public void setMyString(String value) {this.myString = value;}
}// 使用
MyClass obj = new MyClass();
obj.setMyString("new value");

2. 使用反射

如果没有 setter 方法可用,可以使用反射。这种方法可以突破正常的访问控制规则,但应谨慎使用,因为它破坏了封装性,增加了代码的复杂性和出错的可能性。并且性能并不好。

import java.lang.reflect.Field;public class MyClass {private String myString = "initial value";
}// 使用反射修改
MyClass obj = new MyClass();
try {Field field = MyClass.class.getDeclaredField("myString");field.setAccessible(true); // 使得private字段可访问field.set(obj, "new value");
} catch (NoSuchFieldException | IllegalAccessException e) {e.printStackTrace();
}

相关文章:

Java基础扫盲(二)

想看Java基础扫盲&#xff08;一&#xff09;的可以观看我的上篇文章Java基础扫盲 目录 String为什么设计为不可变的 String有长度限制吗 为什么JDK9将String的char[]改为byte[] 泛型中K,T,V,E,Object,?等都代表什么含义 怎么修改一个类中使用了private修饰的String类型…...

兼容React的刮刮乐完整代码实现

需要兼容React的刮刮乐完整代码实现 在现代Web开发中&#xff0c;React作为一种流行的前端框架&#xff0c;为开发者提供了构建动态界面的强大工具。刮刮乐效果作为一种趣味性的用户交互&#xff0c;能够显著提升用户体验和参与度。本文将详细介绍如何在React项目中实现一个兼…...

PHP程序如何实现限制一台电脑登录?

PHP程序如何实现限制一台电脑登录&#xff1f; 可以使用以下几种方法&#xff1a; 1. IP地址限制&#xff1a;在PHP中&#xff0c;可以通过获取客户端的IP地址&#xff0c;然后与允许登录的IP地址列表进行比对。如果客户端的IP地址不在列表中&#xff0c;就禁止登录。 “php $…...

nodejs fs 模块的简介与相关案例

fs 文件系统模块 什么是 fs 文件系统模块&#xff1f; fs 模块是 Node.js 官方提供的、用来操作文件的模块。它提供了一系列的方法和属性&#xff0c;用来满足用户对文件的操作要求。* 例如&#xff1a; fs.readFile() 方法用来读取文件内容。fs.writeFile() 方法用来写入文…...

计算机毕业设计 基于Flask+Vue的博客系统 Python毕业设计 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…...

基于SSH的酒店管理系统的设计与实现 (含源码+sql+视频导入教程)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSH的酒店管理系统拥有两种角色 管理员&#xff1a;房间管理、房型管理、客户管理、预定管理、入住管理&#xff08;到店入住、预定入住、正在入住&#xff09;、账单管理、会员管理…...

消息队列10:为RabbitMq添加连接池

环境&#xff1a; win11rabbitmq-3.8.17.net 6.0RabbitMQ.Client 6.8.1vs2022 安装RabbitMq环境参照&#xff1a; window下安装rabbitmqlinux下安装rabbitmq 问题&#xff1a;rabbitmq的c#客户端没有自带连接池&#xff0c;所以需要手动实现。 简易实现如下&#xff1a; usi…...

在使用 Docker 时,用户可能会遇到各种常见的错误和问题

在使用 Docker 时&#xff0c;用户可能会遇到各种常见的错误和问题。以下是一些需要注意的常见错误及其可能的解决方案&#xff1a; 1. 权限问题 在 Linux 系统上运行 Docker 命令时&#xff0c;可能会遇到权限不足的问题。解决这个问题通常有两种方法&#xff1a; 使用 sud…...

MinIO使用客户端进行桶和对象的管理

MinIO使用客户端进行桶和对象的管理 minio安装完成后&#xff0c;除了自带的webui管理界面&#xff0c;还可以使用官方配套的客户端mc进行管理。除此之外&#xff0c;还可以使用第三方客户端s3browser也可以完成对象和桶的生命周期管理。 1. 官方客户端mc MinIO客户端 mc 命…...

数据库管理-第244期 一次无法switchover的故障处理(20240928)

数据库管理244期 2024-09-28 数据库管理-第244期 一次无法switchover的故障处理&#xff08;20240928&#xff09;1 问题展现2 问题排查与处理2.1 问题12.2 问题2 3 问题分析4 总结 数据库管理-第244期 一次无法switchover的故障处理&#xff08;20240928&#xff09; 作者&…...

太绝了死磕这本大模型神书!

今天给大家推荐一本大模型神书&#xff0c;就是这本&#xff1a;《大语言模型&#xff1a;基础与前沿》 书籍介绍&#xff1a; 本书深入阐述了大语言模型的基本概念和算法、研究前沿以及应用&#xff0c;涵盖大语言模型的广泛主题&#xff0c;从基础到前沿&#xff0c;从方法…...

Kevin‘s notes about Qt---Episode 6 不同类中创建同一对象

问题描述 使用场景 现在在我的Qt界面中需要同时使用采集卡的AI(Analog Input)和AO(Analog Output)功能,均已分别调通,但是像之前一样通过创建两个类,然后分别在两个线程中进行操作的方式并不能实现。 原本写法 头文件 art_ao.h 核心代码如下: #ifndef ART_AO_H #defi…...

YOLOv9改进策略【Conv和Transformer】| AssemFormer 结合卷积与 Transformer 优势,弥补传统方法不足

一、本文介绍 本文记录的是利用AssemFormer优化YOLOv9的目标检测网络模型。传统卷积和池化操作会导致信息丢失和压缩缺陷,且传统的注意力机制通常产生固定维度的注意力图,忽略了背景中的丰富上下文信息。本文的利用AssemFormer改进YOLOv9,以在特征传递和融合过程中增加多尺…...

Git 的安装和配置

Git 是跨平台的&#xff0c;可以在 Windows&#xff0c;Linux、Unix 和 Mac 各几大平台上使用 由于笔者主要是使用 Windows&#xff0c;其他平台下安装 Git 的方法暂且不表&#xff08;可参考廖雪峰老师的博客&#xff1a;安装 Git&#xff09; ‍ Windows 安装 Git 从 Git…...

InternVL 微调实践

任务 follow 教学文档和视频使用QLoRA进行微调模型&#xff0c;复现微调效果&#xff0c;并能成功讲出梗图. 复现过程 参考教程部署&#xff1a;https://github.com/InternLM/Tutorial/blob/camp3/docs/L2/InternVL/joke_readme.md 训练 合并权重&&模型转换 pyth…...

自然语言处理在人工智能领域的发展历程,以及NLP重点模型介绍

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下自然语言处理在人工智能领域的发展历程&#xff0c;以及NLP重点模型介绍。本文详细介绍了自然语言处理的发展历程&#xff0c;同时深入探讨了各种自然语言处理模型的原理与应用。文章首先回顾了自然语言处理技术的发…...

Replit Agent:AI驱动的全自动化软件开发革命

目录 引言Replit Agent核心功能使用场景与优势最新版本更新处理复杂项目的能力常见问题解决方案支持的编程语言和技术栈与其他AI编程工具的比较结语 引言 在人工智能快速发展的今天&#xff0c;软件开发领域正经历着前所未有的变革。Replit Agent作为AI初创公司Replit推出的…...

SAP调用发起泛微OA流程

SAP调用泛微Servlet接口&#xff0c;发起流程 编写servlet接口&#xff0c;给SAP调用 public class SAPCreateWorkflow extends HttpServlet{private static final long serialVersionUID 1L;public void doPost(HttpServletRequest request, HttpServletResponse response)…...

JAVA毕业设计184—基于Java+Springboot+vue3的企业信用信息管理系统(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootvue3的企业信用信息管理系统(源代码数据库)184 一、系统介绍 本项目前后端分离(可以改为ssm版本)&#xff0c;分为用户、管理员两种角色 1、用户&#xff1a; …...

webshell-HTTP常见特征

一、总体特点 二、蚁剑 数据中可以看到一些明文字符串函数&#xff0c;响应中可以看到响应的明文数据。 ant特征以及对数据base64可以解码 chr类别的会出现大量的chr编码 大量的百分号字符 三、哥斯拉 第一个请求包很大 响应为0 密钥被拆分到数据前后 响应包cookie带&#xf…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...