java中初始化字符串的大小

Bis*_*128 8 java compiler-construction javac

显然,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 });
Run Code Online (Sandbox Code Playgroud)

}

Paŭ*_*ann 19

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

CONSTANT_Utf8_info {
    u1 tag;
    u2 length;
    u1 bytes[length];
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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


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

将对象传递给BMethod.invoke(并且类似于BConstructor.newInstance)时,它可以是BObject(即现有对象的包装器,它将传递包装的对象),String(将按原样传递),或者还要别的吗.在最后一种情况下,对象将转换为字符串(by toString()),然后将此字符串解释为Java表达式.

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

code_length项的值必须小于65536.

这就是为什么它打破了更长的阵列.


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

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

  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;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    (这是为了创建一个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;
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

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

    Object result = method.invoke(obj, new Object[] { bArray });
    
    Run Code Online (Sandbox Code Playgroud)