显然,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 });
}
答案 0 :(得分:19)
字符串文字的长度(即"..."
)受类文件格式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-8中编码为代理对的那些(即U + 10000到U + 10FFFF)每个占用6个字节。
(标识符的限制相同,即类,方法和变量名称,以及这些标识符的类型描述符,因为它们使用相同的结构。)
Java语言规范未提及string literals的任何限制:
字符串文字由用双引号括起来的零个或多个字符组成。
因此,原则上,编译器可以将较长的字符串文字拆分为多个CONSTANT_String_info
结构,并通过连接(以及.intern()
- 结果)在运行时重构它。我不知道是否有任何编译器实际上是这样做的。
它表明问题与字符串文字无关,而与数组初始值设定项有关。
当将对象传递给BMethod.invoke
(和BConstructor.newInstance类似)时,它可以是BObject(即现有对象的包装器,然后它将传递包装的对象),一个String(其中)将按原样传递,或其他任何东西。在最后一种情况下,对象将被转换为字符串(通过toString()
),然后该字符串被解释为Java表达式。
为此,BlueJ将此表达式包装在类/方法中并编译此方法。在该方法中,数组初始化器简单地转换为一长串的数组赋值...这最终使该方法比Java方法的maximum bytecode size更长:
code_length项的值必须小于65536。
这就是它打破更长阵列的原因。
因此,要传递更大的数组,我们必须找到一些其他方法将它们传递给BMethod.invoke。 BlueJ扩展API无法创建或访问包含在BObject中的数组。
我们在聊天中发现的一个想法是:
在项目内(或在新项目中,如果可以互操作)创建一个新类,如下所示:
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;
}
}
(这是创建int[]
的情况 - 如果你还需要其他类型的数组,它可以
也可以更通用。此外,通过使用它可以提高效率
内部int[]
作为存储,随着它的增长偶尔扩大它,以及int makeArray
做最后的arraycopy。这是一个草图,因此这是最简单的实现。)
从我们的扩展程序中,创建此类的对象,
并通过调用.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对象,并为每次数组转换缓存一次而不是一次。)
如果通过某种算法生成数组内容,则可以在此处执行此生成,而不是先创建另一个包装对象。
在我们的扩展中,调用我们实际想要用long数组调用的方法,传递我们的包装数组:
Object result = method.invoke(obj, new Object[] { bArray });
答案 1 :(得分:-1)
字符串长度受Integer.MAX_VALUE
的限制答案 2 :(得分:-2)
如果type为number max length = Integer.MAX_VALUE,如果type为char max length = 65536