简体   繁体   中英

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 :

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:

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.

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.

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.

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 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.

So it is conceptual. You have no objects layouted on the stack (some JVMs do it sneakily), and: objects are indirect .

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:

 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.

We could implement a class that stored a T type object and returns it:

 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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