精华内容
下载资源
问答
  • String长度限制

    千次阅读 2020-04-16 11:05:16
    有两种情况会遇到String长度超出限制的问题:1. 别人对文件进行Base64加密后传过来,然后你把接收到的字符串粘到代码里,会提示字符串过长,其实这是编译期字符串长度的限制问题;2. 有那种在java代码里用字符串写...

    有两种情况会遇到String长度超出限制的问题:1. 别人对文件进行Base64加密后传过来,然后你把接收到的字符串粘到代码里,会提示字符串过长,其实这是编译期字符串长度的限制问题;2. 有那种在java代码里用字符串写sql的情况,字符串长度太长也不行。

    字符串长度的问题其实要分两种情况:编译期和运行期。

    1. 编译期

    package com.linyf.demo;
    
    import org.apache.commons.codec.binary.Base64;
    
    import java.io.*;
    
    public class StringLengthDemo {
        public static void main(String[] args) throws IOException {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            InputStream is = new FileInputStream(new File("C:\\Users\\86183\\Pictures\\174718-1558172838db13.jpg"));
            byte[] bytes = new byte[1024];
            int len = -1;
            while ((len = is.read(bytes))!=-1){
                baos.write(bytes,0,len);
            }
    	//模拟s就是别人传过来的Base64加密后的文件字符串,然后输出后赋值给aaa 运行编译会报错:字符串长度过长
            String s = Base64.encodeBase64String(baos.toByteArray());
            System.out.println(s);
            System.out.println(s.length());
    //        String aaa = "a...a";
    
    //        System.out.println(aaa);

    当我们定义字符串常量,如String a=’‘aaa’'的时候,会把字符串aaa在常量池中存储一份。所以编译期的字符串长度其实受常量池限制。

    字符串在class格式文件中的存储格式:

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

    u2是无符号的16位整数,因此理论上允许的string str的最大长度是2^16=65536,但是class 文件中null 值使用两个 字节来表示,因此只剩下 65536- 2 = 65534个字节。

    oracle VM 官网中关于class文件格式说明中有下面两段话:
    在这里插入图片描述
    可以看到所有需要保存在常量池中的数据,长度最大不能超过65535
    在这里插入图片描述
    可以看到class 文件是使用一种变体UTF-8格式来存放字符的,null 值使用两个 字节来表示,而不是一个字节。

    2. 运行期

    String构造函数:
    在这里插入图片描述
    而length为int,也就是长度最大值为Integer.MAX_VALUE = 2^31 - 1即2147483647 。因为int是32位有符号位,只取正值的话,通过计算,String长度最大大概是4G:

    2147483647 * 16 = 3435973835234359738352 / 8 = 4294967294 (Byte)
    4294967294 / 1024 = 4194303.998046875 (KB)
    4194303.998046875 / 1024 = 4095.9999980926513671875 (MB)
    4095.9999980926513671875 / 1024 = 3.99999999813735485076904296875 (GB)
    展开全文
  • 1 String的形式public final class StringString类是由final修饰的,所以是不能被继承的①,我们在对字符串进行比较时,一般是期望对比其中的字符串是否一样,所以这里我们不能用"=="进行字符串的比较,而是需要使用...

    1 String的形式

    public final class String

    String类是由final修饰的,所以是不能被继承的①,我们在对字符串进行比较时,一般是期望对比其中的字符串是否一样,所以这里我们不能用"=="进行字符串的比较,而是需要使用"equals"方法②,因为使用==进行比较时,是比较的对象,只有指向同一个字符串对象的才会是true,否则就算字符串值相同也可能出现不相等的情况。

    private final char value;

    String的值实际上是以char的数组存储的,并且是final的,所以字符串对象是不可变的③,但是我们可以看到字符串的一些操作会误导我们,比如使用:

    String a = "aaaa";a += "bbbb";

    其实这个时候a已经指向新的对象地址。

    到这里为止,初级工程师都应该很熟悉。

    2 String的形式

    在思考String能有多长之前,我们先看下String定义的不同形式。

    // 第一种String s = "aaaaaaaaaaaaa...";// 第二种byte a = readFromFile(new File("someLargeText.txt"));String superLongString = new String(a);

    那么既然思考String的长度,那就应该想想为什么会有长度的限制,难道我在编译器里定义一个String时,有多长不是随便我们自己输入吗?还有上面两种方式有什么区别呢?

    2.1 字面量的形式

    对于第一种是字面量,Java将其存在常量池中,在Java1.6的版本中是在栈的常量池中,在1.7、1.8版本中将其放到了堆的常量池中。那就是说第一种这种方式中是受到常量池大小的约束了,不错,是会受到常量池的约束,但是在运行在JVM之前,被编译成字节码时就已经有了限制。

    17768f28037b9c4a1bfe49d130c2c496.png

    如上图所示,编译后的length的类型为u2(无符号16位),也就是讲length的最大值为2^16-1 = 65535,那就是讲我们的上面的字符串s长度按MUTF-8(字节码中的编码)编码可以存储65535个字节。

    到这里为止,如果你是中级工程师,知道这么多已经很不错了。

    可是事实上呢,我们实验后发现只能存储65534个字节,这是为什么呢?网上有很多猜想,大部分不正确。我们扒一下Java编译器的源码,会发现:

    5a75431a8a8c18b736cb6cc1920299bb.png

    这下大家明白了吧,Java编译器在检查字符串常量时,判断的是长度只有<65535才会正常,否则报错。看起来像是编译器的Bug。如果你会修改编译器源码,你将上面的判断条件改成<=65535,这样你存一个65535个字符"a"的字符串就不会编译出错了。

    我们知道上面我们是用拉丁字符"a"来测试的,a使用UTF-8编码刚好是一个字节,所以可以存储65534个,那如果存汉字呢,比如我们经常看到的"烫",它使用TF-8编码后占用三个字节,那么也就是说我们可以这样定义:

    // 按照我们刚才的分析,应该可以存储65534/3个"烫"汉字String s = "烫烫烫...烫烫";

    那我们尝试存储65535/3个汉字"烫"试试呢?结果是可以的,并没有报错。诶?这是为什么呢?我们继续扒下编译器的源码看到:

    52cee0d0d1c12a4c7023dd1aec743d64.png

    编译处理汉字这种的呢,他判断的逻辑不一样。条件是>65535才会抛异常,也就是小于等于65535是正常的。很有意思,写Java编译器的人也很有意思哈。

    2.1 new的形式

    对于第二种形式的,很显然只有在运行时受限于Java虚拟机了。我们知道String最后保存在char数组中,Java虚拟机是如何做的呢?简单参考下源码:

    88798ab39d80b43e8f56915694edb21b.png

    虚拟机指令newarray [int],size是以整形定义的,所以它的限制其实就是int的最大值,但是在有一些虚拟机上会保留一些头信息在数组中,所以就变成了Integer.MAX_VALUE - 8个char;

    到这里呢,基本上你就有了高级工程师的思考高度了。

    3

    总结

    3.1 字面量的形式

    • 受字节码数据结构的限制,字符串使用MUTF-8编码后字节数不超过65535

    • 拉丁字符,受Java编译器代码限制,最多只能存储65534个字节

    • 非拉丁字符,最多存储65535个字节

    3.2 new的形式

    • 受虚拟机指令限制,字符数理论上线是Integer.MAX_VALUE,但是实际上有保留头信息的部分,所以会略小

    • 受堆内存的限制,如果堆内存很小,那就不能超过堆内存的限制

    看起来本文有点过于追求细节了,有点孔乙己的回字有几种写法的意思。实际则不然,搞技术就是要把握好细节,才能写出优秀的代码,才能成为高阶的工程师而不是码农。

    如果看到这里,说明你喜欢这篇文章,请转发

    展开全文
  • JAVA中string长度限制

    2020-03-10 11:57:05
    不同的时期限制不一样。 01 编译期 String的源码入手,根据public String(char value[], int offset, int count)的定义,count是int类型的,所以,char value[]中最多可以保存Integer.MAX_VALUE个,即2147483647...

    这个问题要分两个阶段看,分别是编译期和运行期。不同的时期限制不一样。

    01 编译期

    String的源码入手,根据public String(char value[], int offset, int count)的定义,count是int类型的,所以,char value[]中最多可以保存Integer.MAX_VALUE个,即2147483647字符。

    但是,实验证明,String s = "";中,最多可以有65534个字符。如果超过这个个数。就会在编译期报错。

    public static void main(String[] args) {
    
              String s = "a...a";// 共65534个a
    
              System.out.println(s.length());
    
              String s1 = "a...a";// 共65535个a 报错编译不过
    
              System.out.println(s1.length());
    
    }

    明明说好的长度限制是2147483647,为什么65535个字符就无法编译了呢?

    当我们使用字符串字面量直接定义String的时候,是会把字符串在常量池中存储一份的。那么上面提到的65534其实是常量池的限制。

    常量池中的每一种数据项也有自己的类型。Java中的UTF-8编码的Unicode字符串在常量池中以CONSTANT_Utf8类型表示。

    CONSTANTUtf8info是一个CONSTANTUtf8类型的常量池数据项,它存储的是一个常量字符串。常量池中的所有字面量几乎都是通过CONSTANTUtf8info描述的。CONSTANTUtf8_info的定义如下:

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

    u2是无符号的16位整数,因此理论上允许的的最大长度是2^16=65536。而 java class 文件是使用一种变体UTF-8格式来存放字符的,null 值使用两个 字节来表示,因此只剩下 65536- 2 = 65534个字节。

    02 运行期

    上面提到的这种String长度的限制是编译期的限制,也就是使用String s= "";这种字面值方式定义的时候才会有的限制。

    那么。String在运行期有没有限制呢,答案是有的,就是我们前文提到的那个Integer.MAX_VALUE ,这个值约等于4G,在运行期,如果String的长度超过这个范围,就可能会抛出异常。(在jdk 1.9之前)

    int 是一个 32 位变量类型,取正数部分来算的话,他们最长可以有

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

     

    展开全文
  • 首先我们直接揭晓答案,String类型是有长度限制的并且它在变异环境和运行时环境限制是不同的。下面我们会详细展开分析。 一、String源码分析 首先我们进入到String源码中看看是否能找到一些有用的线索,是否有直接对...

    前言

    在我们工作和学习中基本离不开Sring的数据类型,虽然我们经常接触到它但是一般很少会有人关心String是否会像int,long一样有范围限制。如果有的话又会是多少呢?首先我们直接揭晓答案,String类型是有长度限制的并且它在变异环境和运行时环境限制是不同的。下面我们会详细展开分析。

    一、String源码分析

    首先我们进入到String源码中看看是否能找到一些有用的线索,是否有直接对长度的限制或定义。String类中有很多重载的构造函数,其中有几个是支持用户传入length来定义长度的。可以看到,这里面的参数length是使用int类型定义的,那么也就是说,String定义的时候,最大支持的长度就是int的最大范围值。那么,我们是不是就可以认为String能支持的最大长度就是,java.lang.Integer#MAX_VALUE的最大值是2^31 - 1这个值了呢?事情当然没有那么简单,这个值只是在运行期,我们构造String的时候可以支持的一个最大长度,而实际上,在编译期,定义字符串的时候也是有长度限制的。
    在这里插入图片描述
    下面我就事实说话,这个字符串是我随便输出到控制台长度为10万的一个字符串。此时此刻它远远没有达到2^31 - 1但是却编译报错提示我们常量字符串过长。这又是为什么呢?
    在这里插入图片描述
    我们都知道,如我们所定义的“0123456789…”俗称字面量,在编译之后会以常量的形式进入到Class常量池。而常量池又是有所限制的,以至于间接性的限制了编译时期String的长度。

    二、编译期常量池限制

    我们知道,javac是将Java文件编译成class文件的一个命令,那么在Class文件生成过程中,就需要遵守一定的格式。根据 《Java虚拟机规范》中第4.4章节常量池的定义,CONSTANT_String_info 用于表示 java.lang.String 类型的常量对象,格式如下:
    在这里插入图片描述
    地址:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.3

    Stirng 长度之所以会受限制,是因JVM规范对常量池有所限制。常量池中的每一种数据项都有自己的类型。其中,string_index 项的值必须是对常量池的有效索引, 常量池在该索引处的项必须是 CONSTANT_Utf8_info 结构,表示一组 Unicode 码点序列,这组 Unicode 码点序列最终会被初始化为一个 String 对象。
    CONSTANT_Utf8的数据结构如下:

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

    什么是码点?

    在这里插入图片描述
    上图出自:https://www.cnblogs.com/benbenalin/p/6921553.html

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

    //65535个字符,编译报错
    String s = "111111111......";
    
    //65534个字符,编译通过
    String s1 = "11111111......";
    

    下图字符串s中包含65535个1编译出错,当我删除掉一个1时编译通过。这也直接验证了String编译时期的长度限制为65534
    在这里插入图片描述
    其实,这个原因在javac的代码中是可以找到的,在Gen类中有如下代码:

    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的时候,就会导致编译失败。有兴趣的可以自己下一份源码翻阅下。其实,关于这个值,在《Java虚拟机规范》也有过说明:

    if the Java Virtual Machine code for a method is exactly 65535 bytes long and ends with an instruction that is 1 byte 
    long, then that instruction cannot be protected by an exception handler. A compiler writer can work around this bug by 
    limiting the maximum size of the generated Java Virtual Machine code for any method, instance initialization method, or 
    static initializer (the size of any code array) to 65534 bytes
    
    如果方法的Java虚拟机代码恰好是65535字节长,并且以一条1字节长的指令结束,那么该指令就不能被异常处理程序保护。编译器编者可以通过将为任何方
    法、实例初始化方法或静态初始化器(任何代码数组的大小)生成的Java虚拟机代码的最大大小限制为65534字节来解决这个问题
    

    三、运行时期限制

    上面我们提到在编译时期定义String s = “xxx”;最大为65534,那运行时期如果继续给这个变量追加字符串进去是否会报错呢?答案是不会,这里我就不进行演示了。那么它的边界限定又会是多少呢,总不能是无限大吧。当然不可能它的最大值就是我们前文提到的那个Integer.MAX_VALUE ,这个值约等于4G,在运行期,如果String的长度超过这个范围,就可能会抛出异常。(在jdk 1.9之前)

    (2^31-1)*2*16/8/1024/1024/1024 = 4GB
    

    所以在最坏的情况下,一个最大的字符串要占用4GB的内存。如果你的虚拟机不能分配这么多内存的话,会直接报错的。JDK9以后对String的存储进行了优化。底层不再使用char数组存储字符串,而是使用byte数组。对于LATIN1字符的字符串可以节省一倍的内存空间。

    具体可以通过下图了解:
    在这里插入图片描述
    地址:https://www.cnblogs.com/flydean/p/jdk9-string-compact.html

    总结:

    字符串有长度限制,在编译期,要求字符串常量池中的常量不能超过65535,并且在javac执行过程中控制了最大值为65534。在运行期,长度不能超过Int的范围,否则会抛异常。

    展开全文
  • JAVA中String长度限制解决

    千次阅读 热门讨论 2019-05-08 14:58:52
    今天在公司的时候,同事给了我一个10兆的webservice接口返回的数据文本,刚开始定义String str="123...";编译不通过。特此记录。下面给出解决方案: String str="123......",这样定义的字符串是存在字符串池中的。...
  • Java中的String长度限制

    千次阅读 2019-08-21 10:49:27
    的形式来定义String对象的时候,""中字符的个数有没有限制呢?既然是合理的推断,那就要要足够的依据,所以我们可以从String的源码入手,根据public String(char value[], int offset, int count)的定义,count是int...
  • [Java] String 长度限制

    万次阅读 2017-03-10 16:30:07
    一、Java String 变量长度限制根据 String 源码: 因此,理论上 String 变量长度限制为 int 类型的最大值,即 Integer.MAX_VALUE = 2^31 - 1 = 2147483647,约等于 2G。注:实际还和 java 堆内存大小有关。二、Java ...
  • 来源:r6d.cn/Fmku前言话说Java中String是有长度限制的,听到这里很多人不禁要问,String还有长度限制?是的有,而且在JVM编译中还有规范,而且有的家人们在面试的时候...
  • Java中String长度限制解析

    千次阅读 2020-10-22 14:40:56
    Java虚拟机规范摘要 每个 Class 文件都是由 8 字节为单位的字节流组成,所有的 16 位、32 位和 64 位长度的数 据将被构造成 2 个、4 个和 8 个 8 字节单位来表示。
  • String 有没有长度限制呢 1、String的数据结构是 char value[]。数组的长度是int类型,最大值为2的31次方-1= 2147483647(2G),所以String最多存储2147483647 个字符。 private final char value[]; public int ...
  • 字符串还有长度限制?是的没错。 先看简单的情况。 // 并不是显示的在类中new,请看后面注意 String str = new String("str"); 如果通过new的方法来创建String,可以通过String的另一个构造方法得出,长度的限制是...
  • hive 中String长度没有限制

    千次阅读 2020-12-10 11:43:53
    hive 中String长度没有限制! hive的string和varchar的区别 Hive有2种类型用于存储变长文本。 1.Hive-0.12.0版本引入了VARCHAR类型,VARCHAR类型使用长度指示器(1到65355)创建,长度指示器定义了在字符串中允许...
  • String有没有长度限制

    千次阅读 2019-05-09 10:36:57
    但使用字符串直接定义String的时候,会把字符串在常量池中存储一份,常量池的最大容量限制是65534,所以如果String大于65534字符长度就会编译报错 · 在Java中,所有保存在常量池中的数据,长度都不可大于65535 ...
  • golang中string长度

    万次阅读 2020-10-12 02:45:33
    golang中计算string长度用len函数,但是len函数返回的是字符串的 byte 数量 如果要得到字符串的字符数,可使用 "unicode/utf8" 包中的 RuneCountInString(str string) (n int) 因为string中不一定都是ASCII ...
  • 作者:Java之道 String采用的是动态分配内存。编译期:当我们使用字符串字面量直接...常量池的限制为65534,也就是说,在Java中,所有需要保存在常量池中的数据,长度最大不能超过65535。(2)运行期:在运行期,如果Strin...
  • java String大小限制

    千次阅读 2019-06-26 10:33:29
    在内存中的表现形式 转载自:https://blog.csdn.net/ifwinds/article/details/80849184(感谢作者) 看一段代码: String s1 = "AB"; String s2 = new String("AB"); String s3 = "A"; String s4 = "B...
  • 关于String有没有长度限制的问题,我之前单独写过一篇文章分析过,最近我又抽空回顾了一下这个问题,发现又有了一些新的认识。于是准备重新整理下这个内容。 这次在之前那篇文章的基础上除了增加了一些验证过程外,...
  • Java 中的 String 有没有长度限制

    千次阅读 2020-05-27 18:18:47
    作者 l Hollis来源 l Hollis(ID:hollischuang)关于String有没有长度限制的问题,我之前单独写过一篇文章分析过,最近我又抽空回顾了一下这个问题,发现又有...
  • 关于String长度限制

    万次阅读 2011-07-30 19:15:41
    要理解 java 中String的运作方式,必须明确一点:String 是一个非可变类(immutable)。 什么是非可变类呢?简单说来,非可变类的实例是不能被修改的,每个实例中包含 的信息都必须在该实例创建的时候就提供出来,...
  • android 字符长度限制

    千次阅读 2017-12-20 14:24:41
    public static String handleText(String str, int maxLen) { if (TextUtils.isEmpty(str)) { return str; } int count = 0; int endIndex=0; for (int i = 0; i (); i++) {
  • 数据注解对string类型长度的约束

    千次阅读 2019-01-25 16:29:49
    Required :可以过滤 “”、" " MaxLength(8) :不能过滤 “”、&...StringLength(8) :不能过滤 “”、" " 所以感觉MaxLength和StringLength功能一样。 能否对列表里的string作约束?不能。 ...
  • Java 中的 String 有没有长度限制

    千次阅读 2019-08-16 11:07:01
    转载: ...String是Java中很重要的一个数据类型,除了基本数据类型以外,String...就如本文我们要讨论的问题:Java中的String有没有长度限制? 这个问题要分两个阶段看,分别是编译期和运行期。不同的时期限制不一样。...
  • 对于字符串可以承受的最大长度,要分为2个阶段,一个是编译时期(也就是你代码定义了一个String字符串,String s= “xiaofang”),一个是运行时期(指在程序运行过程中) 编译期String字符串的限制 我们都知道JVM里面是...
  • 编译期是65535个字符,运行期可以有4G大小容量的字符。 原因: 1、字符串变量声明赋值,进入常量池,必须要遵守常量池规则,JAVA虚拟机规范一文对常量池有规约,...2、运行时长度不能超过Int的范围,否则会抛异常。.
  • java String 最长长度和占用内存大小

    万次阅读 2019-10-25 11:22:01
    String在内存中的最大长度理论上是int型变量的最大值,Integer.MAX_VALUE, String的字面常量的最大长度为CONSTANT_Utf8_info表决定,一般为65535. 二 介绍 1、String的内部实现 通过一个字符数组来维护字符序列,...
  • Golang 求字符串长度之坑

    千次阅读 2019-03-06 17:33:40
    go语言中len()函数可以获取 数组、数组切片,以及ASCII型字符串(如不含汉字)的长度,而字符串因为在go语言中是以utf-8形式储存。所以: str1 := &quot;代码&quot; str2 := &quot;代码使我快乐&...
  • String长度限制 想要搞清楚这个问题,首先我们需要翻阅一下String的源码,看下其中是否有关于长度的限制或者定义。 String类中有很多重载的构造函数,其中有几个是支持用户传入length来执行长度的: public String...
  • 关于String有没有长度限制的问题,我之前单独写过一篇文章分析过,最近我又抽空回顾了一下这个问题,发现又有了一些新的认识。于是准备重新整理下这个内容。 这次在之前那篇文章的基础上除了增加了一些验证过程外,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 251,531
精华内容 100,612
关键字:

string长度限制