- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我想在开发人员试图改变不可变对象(immutable对象)时提醒他。不可变对象(immutable对象)实际上是可变对象的扩展,并覆盖了该对象上的 setter 以使其不可变。
可 rebase 类:Vector3
public class Vector3 {
public static final Vector3 Zero = new ImmutableVector3(0, 0, 0);
private float x;
private float y;
private float z;
public Vector3(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
public void set(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
}
不可变版本:ImmutableVector3
public final class ImmutableVector3 extends Vector3 {
public ImmutableVector3(float x, float y, float z) {
super(x, y, z);
}
//Made immutable by overriding any set functionality.
@Override
public void set(float x, float y, float z) {
throw new Exception("Immutable object."); //Should I even throw an exception?
}
}
我的用例如下:
public class MyObject {
//position is set to a flyweight instance of a zero filled vector.
//Since this is shared and static, I don't want it mutable.
private Vector3 position = Vector3.Zero;
}
假设我团队中的一名开发人员决定他需要操纵对象的位置,但目前它被设置为静态、不可变的 Vector3.Zero 共享 vector 实例。
如果位置 vector 设置为 Vector3.Zero 的共享实例,他最好提前知道他需要创建可变 vector 的新实例:
if (position == Vector3.Zero)
position = new Vector3(x, y, z);
但是,假设他没有先检查这个。我认为,在这种情况下,最好在 ImmutableVector3.set(x,y,z)
方法中抛出一个异常,如上所示。我想使用标准的 Java 异常,但我不确定哪个最合适,而且我也不是 100% 相信这是处理这个问题的最佳方法。
我在(这个问题)[IllegalStateException 是否适合不可变对象(immutable对象)?似乎提出以下建议:
set()
方法不受支持,因为它覆盖了基类,因此这可能是一个不错的选择。元素
。此外,我什至不确定我是否应该在这里抛出异常。我可以简单地不更改对象,也不提醒开发人员他们正在尝试更改不可变对象(immutable对象),但这似乎也很麻烦。在 ImmutableVector3.set(x,y,z)
中抛出异常的问题是 set
必须在 ImmutableVector3
和 vector 3
。所以现在,即使 Vector3.set(x,y,z)
永远不会抛出异常,它也必须放在 try/catch
block 中。
最佳答案
抛出异常通常是可行的方法,您应该使用 UnsupportedOperationException
.
Java API 本身确实在 collections framework 中推荐了这一点:
The "destructive" methods contained in this interface, that is, the methods that modify the collection on which they operate, are specified to throw UnsupportedOperationException if this collection does not support the operation.
另一种方法,如果您创建完整的类层次结构,则创建一个父类(super class) Vector
,它不可修改且没有像 set()< 这样的修改方法
,以及两个子类 ImmutableVector
(保证不变性)和 MutableVector
(可修改)。这会更好,因为你可以获得编译时安全性(你甚至不能尝试修改 ImmutableVector
),但根据情况可能会过度设计(你可能最终会得到很多类).
例如,为 Scala collections 选择了这种方法。 , 它们都存在三种变体。
在您想要修改 vector 的所有情况下,您都使用类型 MutableVector
。在您不关心修改而只想从中读取的所有情况下,您只需使用 Vector
。在所有你想保证不变性的情况下(例如,一个 Vector
实例被传递到构造函数中,你想确保以后没有人会修改它)你使用 ImmutableVector
(它通常会提供一个复制方法,因此您只需调用 ImmutableVector.copyOf(vector)
)。永远不需要从 Vector
进行向下转换,而是指定您需要的正确子类型作为类型。这个解决方案(需要更多代码)的全部要点是类型安全和编译时检查,因此向下转换破坏了这个好处。但是也有异常(exception),例如 ImmutableVector.copyOf()
方法作为优化通常看起来像这样:
public static ImmutableVector copyOf(Vector v) {
if (v instanceof ImmutableVector) {
return (ImmutableVector)v;
} else {
return new ImmutableVector(v);
}
}
这仍然是安全的,并且为您提供不可变类型的另一个好处,即避免不必要的复制。
Guava library拥有大量 immutable collection遵循这些模式的实现(尽管它们仍然扩展了可变的标准 Java 集合接口(interface),因此不提供编译时安全性)。您应该阅读它们的描述以了解有关不可变类型的更多信息。
第三种选择 是只使用不可变 vector 类,根本不使用可变类。出于性能原因使用的可变类通常是过早的优化,如 Java is very good in handling lots of small short-lived temporary objects (由于分代垃圾收集器,对象分配非常便宜,在最好的情况下对象清理甚至可以没有任何成本)。当然,对于像列表这样的非常大的对象,这不是解决方案,但对于 3 维 vector ,这肯定是一个选项(并且可能是最好的组合,因为它简单、安全,并且比其他方法需要更少的代码)。我不知道这个替代方案的 Java API 中的任何示例,因为在创建 API 的大部分部分的日子里,VM 没有那么优化,所以太多的对象可能是一个性能问题。但这不应该阻止您今天这样做。
关于java - 我应该对不可变类的突变尝试抛出异常吗?如果是这样,哪个异常(exception)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18517540/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!