简体   繁体   English

是否有任何内存高效的 Java 等效于 C 联合或 C++ std::variant?

[英]Is There Any Memory-Efficient Java Equivalent to C unions or C++ std::variant?

I have a class Element<T> that contains a T and an int :我有一个包含Tint的类Element<T>

class Element<T>{
    T obj;
    int i;
    // ...
}

When no T is stored, I would like to use obj like a pointer to an Element or an index:当没有存储T ,我想将obj用作指向元素或索引的指针:

obj = someElement;
obj = indexOf(someElement); 

Of course, I can't do that because Java has no unions or variants (as in c++ variants) and has a strict type system.当然,我不能这样做,因为 Java 没有联合或变体(如在 c++ 变体中)并且具有严格的类型系统。

Note that I would like to be able to access an Element through obj, but I have no desire to change it through obj, if that helps.请注意,我希望能够通过 obj 访问 Element,但如果有帮助,我不想通过 obj 更改它。

Questions:问题:

  1. Is there any way to accomplish this without creating my own variant class or installing one?有没有办法在不创建我自己的变体类或安装一个的情况下实现这一点?
  2. If so, what is the most memory efficient way to do this, since I will need to create many Elements?如果是这样,因为我需要创建许多元素,所以最有效的内存方法是什么?

The small problem is conceptual.小问题是概念上的。 An object in java is just some some memory on the heap, and its "address" which is stored in your object field. java中的对象只是堆上的一些内存,其“地址”存储在您的对象字段中。

class MyUnion {
    Object any;
}

MyUnion u = new MyUnion();
u.any = "hello";
u.any = Integer.valueOf(13);

The construct above is a union of "addresses," not of data.上面的构造是“地址”的联合,而不是数据的联合。

The closest to a union is a byte array, wrapped in a ByteBuffer.最接近联合的是一个字节数组,包装在一个 ByteBuffer 中。

ByteBuffer u = ByteBuffer.allocate(8);
u.putDouble(0, 3.14);
long x = u.getLong(0);

For real Object one must "serialize" them in some form:对于真正的对象,必须以某种形式“序列化”它们:

String obj = "Ĉeĥoslovakio";
byte[] b = obj.getBytes(StandardCharsets.UTF_8);
u.putInt(b.length);
u.put(b);

For complex binary data one would use ASN or whatever other systematic technique.对于复杂的二进制数据,可以使用 ASN 或任何其他系统技术。

So it is conceptual.所以它是概念性的。 You have no objects layouted on the stack (some JVMs do it sneakily), and: objects are indirect .您没有在堆栈上布置对象(一些 JVM 偷偷摸摸地这样做),并且:对象是间接的

One way to approach this is by using an interface, or a super class with inheritance.解决此问题的一种方法是使用接口或具有继承的超类。

For example, if we had the following Java interface:例如,如果我们有以下 Java 接口:

 interface Element<T> {
     T getValue();
 }

then any class that implements the Element interface would need to provide a method that returned the value of an element.那么任何实现Element接口的类都需要提供一个返回元素值的方法。

We could implement a class that stored a T type object and returns it:我们可以实现一个存储T类型对象并返回它的类:

 class ElementObject<T> implements Element<T> {

     private T object;

     T getValue() {
         return object;
     }
  }

Or we could implement a class that stores an index and uses it (in conjunction with some big list of objects):或者我们可以实现一个存储索引并使用它的类(结合一些大的对象列表):

 class ElementIndex<T> implements Element<T> {

     private int index;

     T getValue() {
         return bigListOfObjects.get(index);
     }
  }

Now you could create a list or array or Element s and some of them could be ElementObject s and some could be ElementIndex s but they would both provide the access to an element as desired, without any wasted fields in either one.现在您可以创建一个列表或数组或Element ,其中一些可以是ElementObject ,有些可以是ElementIndex但它们都可以根据需要提供对元素的访问,而不会在任何一个中浪费任何字段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM