我需要将原语的动态列表传递给Java方法。可以是(int, int, float)或者(double, char)等等。我知道那是不可能的,所以我在想解决这个问题的有效方法。
因为我正在Android上开发一款游戏,我希望尽可能避免垃圾收集,所以我不想使用任何对象(例如因为自动装箱),而只想使用原始数据类型。因此,在我的例子中,原始类对象的集合或数组(例如Integer)不是一个选项。
所以我在考虑是否可以将一个类对象传递给我的方法,它将包含我需要的所有基本值。然而,这并不能解决我的问题,因为如前所述,原语列表是可变的。因此,如果我在我的方法中这样做,我就不知道如何访问这个动态的原语列表(至少不需要任何对象转换,这是我想要避免的)。
现在我觉得有点迷路了。我不知道在Java中如何解决我的问题的任何其他可能的方法。我希望那只是我缺乏知识。你们中有谁知道没有对象转换的解决方案吗?
提供更多的上下文并解释您想使用此技术的确切目的可能会很有用,因为这可能是决定最佳方法所必需的。
从概念上讲,您正在尝试在任何在托管堆栈上传递参数的语言中总是困难的事情。你希望可怜的编译器做什么?它可以让你在堆栈上推入任意数量的参数,并通过一些堆栈指针算术来访问它们(在C中很好,可以让你随心所欲地使用指针,在Java这样的托管语言中就不那么好了),或者它需要传递对其他地方存储的引用(这意味着分配或某种形式的缓冲区)。
幸运的是,在Java中有几种方法可以有效地传递原语参数。以下是我列出的最有前途的方法,大致是您应该考虑的顺序:
- 重载 -有多个方法,具有不同的基本参数来处理所有可能的组合。如果参数相对较少,可能是最好/最简单/最轻量级的选择。性能也很好,因为编译器会静态地计算出要调用哪个重载方法。
- 原始数组 -传递任意数量的原始参数的好方法。请注意,您可能需要保留一个原始数组作为缓冲区(否则您将不得不在需要时分配它,这违背了避免分配的目标!)。如果你使用部分填充的原始数组,你还需要向数组传递偏移量和/或计数参数。
- 传递带有原语字段的对象 -如果原语字段集事先相对已知,则效果良好。请注意,您还必须保留一个类的实例来充当缓冲区(否则您将不得不在需要时分配它,这违背了避免分配的目标!)。
- 使用专门的原始集合库 -例如Trove库。出色的性能,并且节省了编写大量代码的时间,因为这些库通常都是经过良好设计和维护的。如果这些原语的集合是长期存在的,这是一个很好的选择,也就是说,你不是纯粹为了传递一些参数而创建集合。
- NIO Buffers—在性能方面大致相当于使用数组或原语集合。它们有一点开销,但如果您出于其他原因需要NIO缓冲区,则可能是更好的选择(例如,如果在使用相同缓冲区类型的网络代码或3D库代码中传递原语,或者如果需要将数据传递给本机代码)。它们还可以为您处理偏移量和计数,这可能会有所帮助。
- 代码生成 -编写代码,为专门的基本方法生成适当的字节码(提前或动态)。这并不适合胆小的人,但却是获得绝对最佳性能的一种方法。您可能想使用像ASM这样的库,或者选择一种可以轻松地为您生成代码的JVM语言(Clojure)。
根本没有。在方法中拥有变量数参数的唯一方法是使用...
操作符,该操作符不支持原语。所有泛型也只支持原语。
我唯一能想到的就是这样一个类:
class ReallyBadPrimitives {
char[] chars;
int[] ints;
float[] floats;
}
并在添加时调整数组的大小。但这是非常非常糟糕的,因为你基本上失去了系统中所有的参照完整性。
我不会担心垃圾收集——如果有必要,我会使用对象和自动装箱来解决你的问题(或者更好的是,避免这种"未知的输入参数集",并得到一个可靠的协议)。一旦你有了一个工作原型,看看你是否遇到了性能问题,然后,然后做出必要的调整。您可能会发现JVM处理这些对象的能力比您最初想象的要好。尝试使用...
运算符:
static int sum (int ... numbers)
{
int total = 0;
for (int i = 0; i < numbers.length; i++)
total += numbers [i];
return total;
}
您可以使用BitSet类似于c++位字段。http://docs.oracle.com/javase/1.3/docs/api/java/util/BitSet.html
您也可以将所有原语转换为double
,然后只需传递double
数组。唯一的技巧是你不能使用boolean
类型。
不,像sum(int…数字)不会自动框整型。它会创建一个int[]来保存它们,所以会有一个对象分配;但它不会是per int
public class VarArgs {
public static void main(String[] args) {
System.out.println(variableInts(1, 2));
System.out.println(variableIntegers(1, 2, 3));
}
private static String variableInts(int... args) {
// args is an int[], and ints can't have getClass(), so this doesn't compile
// args[0].getClass();
return args.getClass().toString() + " ";
}
private static String variableIntegers(Integer... args) {
// args is an Integer[], and Integers can have getClass()
args[0].getClass();
return args.getClass().toString();
}
}
输出:class [I
class [Ljava.lang.Integer;