Java 记录用于实现浅不可变的数据载体类型。如果构造函数接受可变类型,那么我们应该实现显式防御性复制以强制不变性。例如
record Data(Set<String> set) {
public Data(Set<Thing> set) {
this.set = Set.copyOf(set);
}
}
Run Code Online (Sandbox Code Playgroud)
这有点烦人 - 我们必须
理想情况下,我们想要表达的是以下内容:
record SomeRecord(ImmutableSet<Thing> set) {
}
Run Code Online (Sandbox Code Playgroud)
或者
record SomeRecord(Set<Thing> set) {
public SomeRecord {
if(set.isMutable()) throw new IllegalArgumentException(...);
}
}
Run Code Online (Sandbox Code Playgroud)
这里我们使用一个虚构的ImmutableSet类型和Set::isMutable方法,在任何一种情况下,记录都是使用规范构造函数创建的 - 很好。不幸的是它不存在!
据我所知,内置集合类型(在 Java 10 中引入)是隐藏的,即无法确定集合是否不可变(除了尝试修改它)。
我们可以使用 Guava,但是当 99% 的功能已经在核心库中时,这似乎有点过分了。或者,有 Maven 插件可以测试注释为不可变的类,但这又是一个创可贴而不是解决方案。
是否有任何纯 Java 机制来强制执行不可变集合?
boolean在JNA结构中传递值时,我正在使用的本机库收到令人惊讶的警告:
value of pCreateInfo->clipped (-1) is neither VK_TRUE nor VK_FALSE
Run Code Online (Sandbox Code Playgroud)
在此库中VK_TRUE,VK_FALSE分别定义为1和0。
结构本身并不是特别复杂,其他所有功能似乎都可以正常工作(本机库似乎将“ undefined”布尔值视为false),但无论如何这里都是这样:
public class VkSwapchainCreateInfoKHR extends Structure {
public int sType;
public Pointer pNext;
public int flags;
public Pointer surface;
public int minImageCount;
public int imageFormat;
public int imageColorSpace;
public VkExtent2D imageExtent;
public int imageArrayLayers;
public int imageUsage;
public int imageSharingMode;
public int queueFamilyIndexCount;
public Pointer pQueueFamilyIndices;
public int preTransform;
public int compositeAlpha;
public int presentMode;
public boolean clipped; // <--------- this …Run Code Online (Sandbox Code Playgroud) 我试图将一组 JNA 结构传递给本机方法,但事实证明它非常繁琐:
假设我们有一个结构:
class MyStructure extends Structure {
// fields...
}
Run Code Online (Sandbox Code Playgroud)
和 JNA 接口中的一个方法:
void pass(MyStructure[] data);
Run Code Online (Sandbox Code Playgroud)
它映射到本机方法:
void pass(const MYStructure* data);
Run Code Online (Sandbox Code Playgroud)
现在的复杂之处在于应用程序正在动态构建这些结构的集合,即我们不是在处理静态数组,而是在处理类似这样的事情:
class Builder {
private final Collection<MyStructure> list = new ArrayList<>();
// Add some data
public void add(MyStructure entry) {
list.add(entry);
}
// Pass the data to the native library
public void pass() {
// TODO
}
}
Run Code Online (Sandbox Code Playgroud)
该pass()方法的一个简单实现可能是:
MyStructure[] array = list.toArray(MyStucture[]::new);
api.pass(array);
Run Code Online (Sandbox Code Playgroud)
(libJNA 库接口在哪里)。
当然这不起作用,因为数组不是连续的内存块 - 足够公平。
一种解决方案是从结构实例分配一个 JNA …