java中初始化字符串的大小

fcy6dtqo  于 2023-01-15  发布在  Java
关注(0)|答案(3)|浏览(221)

很明显,javac中初始化字符串的大小是有限制的。有人能帮我确定最大限制是多少吗?
谢谢

    • 编辑:**

我们正在创建一个初始化字符串,它看起来像"{1,2,3,4,5,6,7,8 ......}",但理想情况下有10,000个数字。当我们为1000个数字这样做时,它工作正常,10,000个抛出一个错误,说代码太大,无法使用try语句。
为了生成这个,我们使用了一个stringbuilder,并循环遍历一个数组来附加值。显然,这是javac的一个限制。我们被告知,如果我们以小块的形式传递数组,我们可以在调用的方法中重建数组。然而,这是不可能的,因为我们无法控制调用的用户方法。
我想邮政编码,但不能,因为这是一个大学的项目。我不是寻找代码的解决方案,只是一些帮助了解这里的实际问题是什么。
它的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 });

}

643ylb08

643ylb081#

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

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

这里的限制因素是length属性,它只有2个字节大,即最大值为65535。这个数字对应于字符串的修改后的UTF-8表示法中的字节数(实际上几乎是CESU-8,但0字符也以两字节形式表示)。
因此,一个纯ASCII字符串最多可以有65535个字符,而由U+0800... U+FFFF范围内的字符组成的字符串只有这些字符的三分之一,而用UTF-16编码的代理对(即U+10000到U+10 FFFF)每个占用6个字节(真实的的UTF-8在这里占用5个字节)。
(The对于标识符(即类、方法和变量名)及其类型描述符也有相同的限制,因为它们使用相同的结构。)
Java语言规范没有提到对字符串常量的任何限制:
字符串文字由双引号中的零个或多个字符组成。
所以原则上,编译器可以将一个较长的字符串常量拆分成多个CONSTANT_String_info结构,然后在运行时通过连接(以及.intern()-ing结果)重新构建它。
它表明问题与字符串文字无关,而是与数组初始化器有关。
当向BMethod.invoke传递一个对象时(类似于BConstructor.newInstance),它可以是BObject(即一个已有对象的 Package 器,它将传递 Package 后的对象),String(它将按原样传递),或者其他任何东西。在最后一种情况下,对象将被转换为一个字符串(由toString()),然后这个字符串被解释为一个Java表达式。
为此,BlueJ将把这个表达式 Package 在一个类/方法中,然后编译这个方法。在这个方法中,数组初始化器被简单地转换成一个长长的数组赋值列表...这最终使得这个方法比Java方法的最大字节码长度还要长:
code_length项的值必须小于65536。
这就是它在较长数组中中断的原因。
因此,要传递更大的数组,我们必须找到其他方法将它们传递给BMethod. invoke。BlueJ扩展API无法创建或访问 Package 在BObject中的数组。
我们在chat中发现的一个想法是这样的:
1.在项目内部(或者在新项目中,如果它们可以互操作的话)创建一个新类,类似于:

public class IntArrayBuilder {
     private ArrayList<Integer> 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;
     }
 }

(This是针对创建int[]的情况--如果您还需要其他类型的数组,也可以使其更通用。此外,使用内部int[]作为存储,随着其增长偶尔扩大它,并使用int makeArray执行最终的数组复制,可以使其更高效。这是一个草图,因此这是最简单的实现。)
1.从我们的扩展中,创建这个类的一个对象,并通过调用它的.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;
 }

(For效率,BClass/BMethod对象实际上可以检索一次并缓存,而不是每次数组转换检索一次。)
如果您通过某种算法生成数组内容,则可以在这里生成,而不必先创建另一个 Package 对象。
1.在我们的扩展中,用long数组调用我们实际想要调用的方法,传递我们的 Package 数组:

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

7gs2gvoe3#

如果类型为数字,则最大长度= Integer.MAX_VALUE;如果类型为字符,则最大长度= 65536

相关问题