java中初始化字符串的大小

显然,javac中初始化字符串的大小是有限制的。 任何人都可以帮我确定最高限度是什么吗?

谢谢

编辑:

我们正在构建一个初始化字符串,它看起来像“{1,2,3,4,5,6,7,8 ……}”,但理想情况下有10,000个数字。 当我们为1000执行此操作时,10,000会抛出错误,说代码对于try语句来说太大了。

为了生成这个,我们使用stringbuilder并循环遍历值的数组。 显然这是javac的一个限制。 我们被告知,如果我们以小块的forms传递它,我们可以在我们调用的方法中重建数组。 然而,这是不可能的,因为我们无法控制我们正在调用的用户方法。

我想发布代码,但不能,因为这是一个大学的项目。 我不是在寻找代码解决方案,只是帮助理解这里的实际问题。

它的for循环是罪犯

Object o = new Object() { public String toString() { StringBuilder s = new StringBuilder(); int length = MainInterfaceProcessor.this.valuesFromData.length; Object[] arrayToProcess = MainInterfaceProcessor.this.valuesFromData; if(length == 0) { //throw exception to do } else if(length == 1) { s.append("{" + Integer.toString((Integer)arrayToProcess[0])+"}"); } else { s.append("{" + Integer.toString((Integer)arrayToProcess[0])+","); //opening statement for(int i = 1; i < length; i++) { if(i == (length - 1)) { //last element in the array so dont add comma at the end s.append(getArrayItemAsString(arrayToProcess, i)+"}"); break; } //append each array value at position i, followed //by a comma to seperate the values s.append(getArrayItemAsString(arrayToProcess, i)+ ","); } } return s.toString(); } }; try { Object result = method.invoke(obj, new Object[] { o }); 

}

字符串文字的长度(即"..." )受类文件格式的CONSTANT_Utf8_info结构的限制,该结构由CONSTANT_String_info结构引用。

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

这里的限制因素是length属性,它只有2个字节大,即最大值为65535.这个数字对应于字符串的修改后的UTF-8表示中的字节数(这实际上几乎是CESU-8) ,但0字符也以双字节forms表示)。

因此,纯ASCII字符串文字最多可包含65535个字符,而由U + 0800 … U + FFFF范围内的字符组成的字符串只有三分之一。 并且以UTF-8编码为代理对的那些(即U + 10000到U + 10FFFF)每个占用6个字节。

(标识符的限制相同,即类,方法和变量名称,以及这些标识符的类型描述符,因为它们使用相同的结构。)

Java语言规范没有提到字符串文字的任何限制:

字符串文字由用双引号括起来的零个或多个字符组成。

因此,原则上,编译器可以将较长的字符串文字拆分为多个CONSTANT_String_info结构,并通过连接(和.intern()结果)在运行时重构它。 我不知道是否有任何编译器实际上这样做。


它表明该问题与字符串文字无关,而与数组初始值设定项有关。

将对象传递给BMethod.invoke (和BMethod.invoke类似)时,它可以是BObject(即现有对象的包装器,然后传递包装对象),String(将按原样传递) ),或其他任何东西。 在最后一种情况下,对象将被转换为字符串(通过toString() ),然后该字符串被解释为Java表达式。

为此,BlueJ将此表达式包装在类/方法中并编译此方法。 在该方法中,数组初始化器简单地转换为一长串的数组赋值…这最终使该方法比Java方法的最大字节码大小更长:

code_length项的值必须小于65536。

这就是它为更长的arrays打破的原因。


因此,要传递更大的数组,我们必须找到一些其他方法将它们传递给BMethod.invoke。 BlueJ扩展API无法创建或访问BObject中包含的数组。

我们在聊天中发现的一个想法是:

  1. 在项目内部(或在新项目中,如果它们可以互操作)创建一个新类,如下所示:

     public class IntArrayBuilder { private ArrayList list; public void addElement(int el) { list.add(el); } public int[] makeArray() { int[] array = new int[list.size()]; for(int i = 0; i < array.length; i++) { array[i] = list.get(i); } return array; } } 

    (这是为了创建一个int[] - 如果你也需要其他类型的数组,它也可以更通用。而且,通过使用内部int[]作为存储,放大它可以提高效率它随着它的增长偶尔会出现,并且int makeArray会做一个最终的arraycopy。这是一个草图,因此这是最简单的实现。)

  2. 从我们的扩展中,创建此类的对象,并通过调用其.addElement方法向此对象添加元素。

     BObject arrayToBArray(int[] a) { BClass builderClass = package.getClass("IntArrayBuilder"); BObject builder = builderClass.getConstructor(new Class[0]).newInstance(new Object[0]); BMethod addMethod = builderClass.getMethod("addElement", new Class[]{int.class}); for(int e : a) { addMethod.invoke(builder, new Object[]{ e }); } BMethod makeMethod = builderClass.getMethod("addElement", new Class[0]); BObject bArray = (BObject)makeMethod.invoke(builder, new Object[0]); return bArray; } 

    (为了提高效率,实际上可以检索一次BClass / BMethod对象,并为每次数组转换缓存而不是一次。)
    如果通过某种算法生成数组内容,则可以在此处执行此生成,而不是首先创建另一个包装对象。

  3. 在我们的扩展中,调用我们实际想要使用long数组调用的方法,传递我们的包装数组:

     Object result = method.invoke(obj, new Object[] { bArray }); 

字符串长度受Integer.MAX_VALUE限制

如果type为number max length = Integer.MAX_VALUE,如果type为char max length = 65536