将原始动态列表传递给Java方法

时间:2011-12-02 00:03:08

标签: java android object primitive

我需要将原始动态列表传递给Java方法。那可能是(int,int,float)或(double,char)或者其他什么。我知道这是不可能的,所以我在想这个问题的有效解决方案。

由于我在Android上开发游戏,我想尽可能避免垃圾收集,我不想使用任何对象(例如因为自动装箱),而只是原始数据类型。因此,在我的情况下,原始类对象的集合或数组(例如Integer)不是一个选项。

所以我在想是否可以将一个类对象传递给我的方法,该方法将包含我需要的所有原始值。但是,这既不是我的问题的解决方案,因为正如所说的基元列表是可变的。因此,如果我在我的方法中采用这种方式,那么我就不知道如何访问这个基元的动态列表(至少没有任何转换到对象,这是我想要避免的)。

现在我觉得有点迷失了。我不知道Java中的任何其他可能的方法如何解决我的问题。我希望这只是我缺乏知识。有没有人知道没有转换到对象的解决方案?

6 个答案:

答案 0 :(得分:1)

提供更多上下文并准确解释您想要使用此技术的内容可能会很有用,因为这可能是决定最佳方法的必要条件。

从概念上讲,您正在尝试在托管堆栈上传递参数的任何语言中执行始终困难的操作。你期望糟糕的编译器做什么?它可以让你在堆栈上推送任意数量的参数并使用一些堆栈指针算法访问它们(在C中很好,你可以随心所欲地使用指针,在Java这样的托管语言中也不是很好)或者它会需要在其他地方传递对存储的引用(这意味着分配或某种形式的缓冲区)。

幸运的是,有几种方法可以在Java中进行高效的原始参数传递。这是我最有希望的方法列表,大致是您应该考虑的顺序:

  • 重载 - 使用具有不同基本参数的多个方法来处理所有可能的组合。如果存在相对较少的参数,可能是最好/最简单/最轻量级的选项。同样出色的性能,因为编译器将静态地计算出要调用的重载方法。
  • 原始数组 - 传递任意数量的原始参数的好方法。请注意,您可能需要将原始数组作为缓冲区保留(否则,您将不得不在需要时分配它,这会使您的目标无法避免分配!)。如果使用部分填充的基本数组,则还需要将偏移和/或计数参数传递给数组。
  • 传递具有基本字段的对象 - 如果预先相对熟知原始字段集,则效果很好。请注意,您还必须保留该类的实例以充当缓冲区(否则您将不得不在需要时分配它,这会破坏您避免分配的目标!)。
  • 使用专门的原始收藏库 - 例如Trove库。{出色的性能,可以节省您编写大量代码,因为这些代码通常都是精心设计和维护的库。如果这些基元的集合将会存在很长时间,那就是很好的选择,即你不是纯粹为了传递一些参数而创建集合。
  • NIO缓冲区 - 大致相当于在性能方面使用数组或原始集合。它们有一些开销,但如果由于其他原因需要NIO缓冲区(例如,如果原语在网络代码或使用相同缓冲区类型的3D库代码中传递,或者如果数据需要,则可能是更好的选择)传递到本地代码或从本机代码传递)。他们还为您处理偏移和计数,这可能会有所帮助。
  • 代码生成 - 编写代码,为专门的原始方法(提前或动态)生成适当的字节码。这不是胆小的,但是获得绝对最佳性能的一种方法。您可能希望使用像ASM这样的库,或者选择一种可以轻松为您生成代码的JVM语言(Clojure可以想到)。

答案 1 :(得分:0)

根本就没有。在方法中使用变量 number 参数的唯一方法是使用不支持基元的...运算符。所有泛型也只支持原语。

我唯一能想到的就是这样的课程:

class ReallyBadPrimitives {
    char[] chars;
    int[] ints;
    float[] floats;
}

在添加数组时调整数组大小。但这真的很糟糕,因为你在系统中基本上失去了所有的参照完整性。

我不担心垃圾收集 - 我会解决你使用对象和自动装箱的问题,如果你必须(或者更好的是,避免这个“未知的输入参数集”并获得可靠的协议)。一旦你有一个工作原型,看看你是否遇到性能问题,然后然后进行必要的调整。您可能会发现JVM可以比您原先想象的更好地处理这些对象。

答案 2 :(得分:0)

尝试使用...运算符:

static int sum (int ... numbers)
        {
           int total = 0;
           for (int i = 0; i < numbers.length; i++)
                total += numbers [i];
           return total;
        }

答案 3 :(得分:0)

您可以使用类似于C ++ Bit字段的BitSet。 http://docs.oracle.com/javase/1.3/docs/api/java/util/BitSet.html

答案 4 :(得分:0)

您还可以将所有基元转换为double,然后传入double数组。唯一的技巧是你不能使用boolean类型。

答案 5 :(得分:0)

Fwiw,像sum(int ...数字)这样的东西不会自动提取整数。它会创建一个int []来保存它们,因此会有一个对象分配;但它不是每个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;