是否可以在Java中使用类似结构的构造?

时间:2011-07-31 19:10:28

标签: java struct

我正在考虑将Java用于大型项目,但我无法在Java中找到任何远程表示结构的东西。我需要能够将网络数据包转换为可以在应用程序中使用的结构/类。

我知道可以使用RandomAccessFile,但这种方式可以接受。所以我很好奇是否有可能将一组字节“强制转换”为像我在C中所做的那样的结构。如果这不可能那么我就不能使用Java。

所以我问的问题是,除了指定对齐方式和数据类型之外,是否可以将对齐的数据转换为类而不需要额外的工作?

8 个答案:

答案 0 :(得分:16)

没有。您不能将一个字节数组转换为类对象。

话虽这么说,你可以使用java.nio.Buffer并轻松地将所需的字段提取到这样的对象:

class Packet {

    private final int type;
    private final float data1;
    private final short data2;

    public Packet(byte[] bytes) {
        ByteBuffer bb = ByteBuffer.wrap(bytes);
        bb.order(ByteOrder.BIG_ENDIAN); // or LITTLE_ENDIAN

        type = bb.getInt();
        data1 = bb.getFloat();
        data2 = bb.getShort();
    }
}

答案 1 :(得分:9)

您基本上是在询问是否可以使用特定于C的解决方案解决另一种语言的问题。可以预见,答案是'不'。

但是,完全可以构造一个在其构造函数中获取一组字节并构造适当实例的类。

class Foo {

  int someField;
  String anotherField;

  public Foo(byte[] bytes) {
    someField = someFieldFromBytes(bytes);
    anotherField = anotherFieldFromBytes(bytes);
    etc.
 }
}

您可以确保将类实例与字节数组进行一对一映射。添加toBytes()方法将实例序列化为字节。

答案 2 :(得分:4)

不,你不能这样做。 Java根本没有与C相同的概念。

您可以创建一个与结构非常相似的类:

public class Structure {
    public int field1;
    public String field2;
}

你可以有一个构造函数,它接受一个或多个字节或DataInput来读取字节:

public class Structure {
    ...
    public Structure(byte[] data) {
        this(new DataInputStream(new ByteArrayInputStream(data)));
    }

    public Structure(DataInput in) {
        field1 = in.readInt();
        field2 = in.readUTF();
    }
}

然后从线上读取字节并将它们泵入Structures

byte[] bytes = network.read();
DataInputStream stream = new DataInputStream(new ByteArrayInputStream(bytes));
Structure structure1 = new Structure(stream);
Structure structure2 = new Structure(stream);
...

它不如C简洁,但它非常接近。请注意,DataInput界面会代表您干净利落地删除任何字符串,因此这绝对比C更有优势。

答案 3 :(得分:1)

没有任何内容符合您的描述。

与Java中的结构最接近的是一个简单的类,它通过它的字段或set / get方法保存值。

在Java类实例和线上表示之间进行转换的典型方法是Java序列化,可以根据需要进行大量自定义。它是Java的远程方法调用API使用的,并且运行得非常好。

答案 4 :(得分:1)

正如约书亚所说,序列化是做这些事情的典型方式。但是,您还有其他二进制协议,如MessagePack,ProtocolBuffers和AvRO。

如果你想玩字节码结构,看看ASM和CGLIB;这些在Java应用程序中非常常见。

答案 5 :(得分:1)

ByteBuffer.wrap(new byte[] {}).getDouble();

答案 6 :(得分:0)

不,这是不可能的。你正试图像C一样使用Java,这必然会引起复杂化。要么学会用Java做事,要么回到C.

在这种情况下,Java方式可能涉及DataInputStream和/或DataOutputStream

答案 7 :(得分:0)

您不能将字节数组转换为类的实例。 但是你可以用java做更多的事情。 Java具有内部的,非常强大且非常灵活的序列化机制。这就是你需要的。您可以在流中读取和写入对象。

如果双方都是用java编写的,那就完全没问题了。如果其中一方不是java,您可以自定义序列化。从阅读java.util.Serializable的javadoc开始。