是否有任何内存高效 Java 等同于 C 联合或 C++ std::variant?
Is There Any Memory-Efficient Java Equivalent to C unions or C++ std::variant?
我有一个 class Element<T>
,其中包含一个 T
和一个 int
:
class Element<T>{
T obj;
int i;
// ...
}
当没有存储 T
时,我想使用 obj
作为指向元素或索引的指针:
obj = someElement;
obj = indexOf(someElement);
当然,我不能那样做,因为 Java 没有联合或变体(如在 c++ 变体中)并且有严格的类型系统。
请注意,我希望能够通过 obj 访问元素,但我不想通过 obj 更改它,如果有帮助的话。
问题:
- 有什么方法可以在不创建我自己的变体的情况下完成这个
class 还是安装一个?
- 如果是这样,执行此操作的内存效率最高的方法是什么,因为我
需要创建很多元素吗?
小问题是概念上的。 java 中的对象只是堆上的一些内存,其“地址”存储在您的对象字段中。
class MyUnion {
Object any;
}
MyUnion u = new MyUnion();
u.any = "hello";
u.any = Integer.valueOf(13);
上面的构造是“地址”而非数据的并集。
最接近联合的是字节数组,包装在 ByteBuffer 中。
ByteBuffer u = ByteBuffer.allocate(8);
u.putDouble(0, 3.14);
long x = u.getLong(0);
对于真正的对象,必须以某种形式“序列化”它们:
String obj = "Ĉeĥoslovakio";
byte[] b = obj.getBytes(StandardCharsets.UTF_8);
u.putInt(b.length);
u.put(b);
对于复杂的二进制数据,可以使用 ASN 或任何其他系统技术。
所以这是概念性的。您没有在堆栈上布局对象(一些 JVM 偷偷地这样做),并且:对象是间接的。
解决此问题的一种方法是使用接口或具有继承的超级 class。
例如,如果我们有以下 Java 接口:
interface Element<T> {
T getValue();
}
那么任何实现 Element
接口的 class 都需要提供一个返回元素值的方法。
我们可以实现一个 class 来存储一个 T
类型的对象和 returns 它:
class ElementObject<T> implements Element<T> {
private T object;
T getValue() {
return object;
}
}
或者我们可以实现一个 class 来存储索引并使用它(结合一些大的对象列表):
class ElementIndex<T> implements Element<T> {
private int index;
T getValue() {
return bigListOfObjects.get(index);
}
}
现在您可以创建一个列表或数组或 Element
s,其中一些可以是 ElementObject
s,一些可以是 ElementIndex
s,但它们都可以提供对一个所需的元素,其中任何一个都没有任何浪费的字段。
我有一个 class Element<T>
,其中包含一个 T
和一个 int
:
class Element<T>{
T obj;
int i;
// ...
}
当没有存储 T
时,我想使用 obj
作为指向元素或索引的指针:
obj = someElement;
obj = indexOf(someElement);
当然,我不能那样做,因为 Java 没有联合或变体(如在 c++ 变体中)并且有严格的类型系统。
请注意,我希望能够通过 obj 访问元素,但我不想通过 obj 更改它,如果有帮助的话。
问题:
- 有什么方法可以在不创建我自己的变体的情况下完成这个 class 还是安装一个?
- 如果是这样,执行此操作的内存效率最高的方法是什么,因为我 需要创建很多元素吗?
小问题是概念上的。 java 中的对象只是堆上的一些内存,其“地址”存储在您的对象字段中。
class MyUnion {
Object any;
}
MyUnion u = new MyUnion();
u.any = "hello";
u.any = Integer.valueOf(13);
上面的构造是“地址”而非数据的并集。
最接近联合的是字节数组,包装在 ByteBuffer 中。
ByteBuffer u = ByteBuffer.allocate(8);
u.putDouble(0, 3.14);
long x = u.getLong(0);
对于真正的对象,必须以某种形式“序列化”它们:
String obj = "Ĉeĥoslovakio";
byte[] b = obj.getBytes(StandardCharsets.UTF_8);
u.putInt(b.length);
u.put(b);
对于复杂的二进制数据,可以使用 ASN 或任何其他系统技术。
所以这是概念性的。您没有在堆栈上布局对象(一些 JVM 偷偷地这样做),并且:对象是间接的。
解决此问题的一种方法是使用接口或具有继承的超级 class。
例如,如果我们有以下 Java 接口:
interface Element<T> {
T getValue();
}
那么任何实现 Element
接口的 class 都需要提供一个返回元素值的方法。
我们可以实现一个 class 来存储一个 T
类型的对象和 returns 它:
class ElementObject<T> implements Element<T> {
private T object;
T getValue() {
return object;
}
}
或者我们可以实现一个 class 来存储索引并使用它(结合一些大的对象列表):
class ElementIndex<T> implements Element<T> {
private int index;
T getValue() {
return bigListOfObjects.get(index);
}
}
现在您可以创建一个列表或数组或 Element
s,其中一些可以是 ElementObject
s,一些可以是 ElementIndex
s,但它们都可以提供对一个所需的元素,其中任何一个都没有任何浪费的字段。