加强不变性

我们都熟悉不变性。一个非常简单的不可变类将是


final class Immutable {

    public final float PI = 3.14;

}

这真的是一成不变的吗?Java开发人员真的不能修改PI吗?不,他们可以使用Reflection API进行访问和修改PI。但是,由于这是一种非常规的访问字段的方式,尽管通过反射API进行的修改可以被安全管理器阻止(对吗?),但是Immutable即使没有激活安全管理器,我们也说这是不可变的。


interface ImmutableName {

    public String getName();

}


class MutableName implements ImmutableName {

    private String name;

    public String getName() { return name; }

    public void setName(String val) { name = val; }

}

如果我将所有MutableName实例称为ImmutableName实例,则开发人员将进行修改name。实际上,开发人员可以检查实例的运行时实现,然后将实例转换为MutableName。Java中的向下转换比反射API更常见,但是它是否仍然是一些非正统的技巧?班级设计者是否应该防御性地编写代码以防止垂头丧气?


呼如林
浏览 128回答 2
2回答

湖上湖

您需要保持透视。是的,从技术上来说,编写可能会干扰我们通常认为是不可变的类的代码是可能的。(如果有人这样做,JLS会很清楚地表明未指定行为。)但这是众所周知的。通常这不是问题,因为:除非绝对必要,否则负责任的程序员不会那样做。我们的大多数同事,同事等都是负责任的。那么,如果您真的认为某人可能会编写疯狂的/不熟练的代码来执行此操作,那么您该怎么办?解决方案:将他们的代码视为不受信任的代码,并对其进行沙箱处理。对您需要信任的代码进行全面的审查。好的,这些方法都不是水密的。但是,IT领域从来没有任何东西。(除非您愿意断开系统与Internet的连接并在法拉第笼中工作。这有时是必要的,但对于普通人而言不是明智的选择。)就其价值而言,Java语言和Java虚拟机设计是在一方面使事情安全和简单,又使程序员能够以性能为名进行聪明的(有时是危险的)事情的折衷方案。如果语言设计师全力以赴地执行诸如不变性之类的事情:这种语言对于目前用于1的大部分语言来说都不实用,许多应用程序的性能将不具有竞争力2,并且无论如何它可能不会起作用3。

LEATH

以完全不同的方式...您的第一个示例询问特定类的不可变性,并且该类在正常意义上被认为是不可变的。(我的另一个答案解释了那应该足够好。)您的第二个示例是关于一个类是否可以违反接口中陈述的关于不变性的假设。显然可以。实际上,不可能以强制接口的所有实现不可变的方式设计Java接口。您不能阻止垂头丧气。同样,您不能阻止某人这样做:class SneakyName implements ImmutableName {    private String name;    public String getName() {        if (SomeOtherClass.beSneaky) {           name += " ";       }       return name;     }}...不需要向下转换即可利用。但是,我们又要真正在这里实现什么呢?如果您只是想避免别人犯错误,那MutableName implements ImmutableName不是错误。如果您要强制人们做正确的事,请使用代码审查。或者,如果您找到了一个足够好的静态代码分析器,则可以随意破坏规则……使用它。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java