接口常量的作用是什么?

8 浏览
0 Comments

接口常量的作用是什么?

我正在学习Java,刚刚发现接口可以拥有字段,这些字段是公共的静态和最终的。到目前为止,我还没有看到这些字段的任何示例。这些接口常量的一些使用案例是什么,我能在Java标准库中看到一些吗?

0
0 Comments

接口常量的用途是什么?

为什么要使用接口常量?

只需比较一下:

public final class Constants {
    private Constants() {
        // 限制实例化
    }
    public static final double PI = 3.14159;
    public static final double PLANCK_CONSTANT = 6.62606896e-34;
}

vs

public interface Constants {
    double PI = 3.14159;
    double PLANCK_CONSTANT = 6.62606896e-34;
}

用法相同,代码量更少。

不良实践?

我认为Thivent的答案强调有误,以下是我的版本:

> 将静态成员放入接口(并实现该接口)是一种不良实践。

Effective Java中的引用假设常量接口将被其他人实现,我认为这不应该(也不会)发生。

当您创建一个名为`Constants`的常量接口时,它不应该由任何人实现(尽管在技术上是可能的,这是唯一的问题)。

标准库不会出现这种情况

标准库无法承担设计的任何可能误用,所以你在标准库中是看不到这种情况的。

然而,对于普通开发者的日常项目来说,使用常量接口要简单得多,因为您不需要担心`static`、`final`、`empty constructor`等问题,它不会导致任何糟糕的设计问题。我唯一能想到的缺点是它仍然有"interface"的名称,但除此之外没有其他问题。

无休止的辩论

最后,我认为每个人都只是引用书中的内容,并对自己的立场进行解释和辩解。我也不例外。也许决定仍然取决于每个项目的开发人员。如果你感觉舒服,就去使用它。我们能做的最好的事情就是让它在整个项目中保持一致。

"将静态成员放入接口(并实现该接口)是一种不良实践。" 不,不是这样的。

修饰符`public`也可以省略,因为它是一个接口,所以它可以简单地写成`double PI = 3.14159;` 使用`Constants.PI`不需要实现`Constants`接口的类!我认为接口的方法更干净,就使用而言。更新。感谢提醒。任何对此有疑问的人可以参考: "所有在接口中定义的常量值都会隐式地是public、static和final的。" - [docs.oracle.com/javase/tutorial/java/IandI/interfaceDef.html](https://docs.oracle.com/javase/tutorial/java/IandI/interfaceDef.html)

0
0 Comments

接口常量的用途是什么?

这个问题的出现原因是因为有人提出了一个关于接口常量的模式是对接口的不当使用。这个假设是基于需要高效地实现不良习惯和实践的有效性之上的。这个假设是基于促进不良软件设计习惯的有效性之上的。

对于这个假设,我在这里写了一篇回应的反驳文章:What is the best way to implement constants in Java?解释了这个假设的无根据性。

这个问题保持了10年的开放状态,直到我发表了反驳这个假设的理由后的2个小时内关闭了,从而暴露了那些深爱着这个错误的假设的人不愿意进行辩论的不情愿。

以下是我对这个假设表达的观点:

- 持有这个假设的基础是需要方法和限制性规则来应对不良习惯和实践的影响。

- 这个观点的支持者无法提供任何其他原因,除了那些由于需要应对这些不良习惯和实践的影响而导致的原因。

- 解决根本问题。

- 然后,为什么不充分利用和利用Java语言结构的每个语言特性以方便自己。不需要夹克。为什么要发明规则来限制你无效的生活方式,以区分和指责更有效的生活方式?

根本问题是信息组织。在工程或补充解决方案之前,应首先了解处理过程中的信息及其行为,以及所谓的业务规则。几十年前,这种信息组织方法被称为数据规范化。只有了解信息组件的粒度和模块化与信息组件的粒度和模块化的对齐才能实施解决方案,这是最佳策略。

组织信息有两个或三个重要障碍:

- 对于数据模型"规范化"的需求缺乏感知力。

- EF Codd关于数据规范化的陈述存在缺陷、缺陷和歧义。

- 最新的伪装成敏捷工程的潮流是错误的观念,即不应该提前计划和调整模块化的组织,因为你可以随着进展进行重构。重构和持续变化而不受未来发现的阻碍被用作借口。然后,通过使用会计手段延迟利润和资产化,从而将过程信息的重要发现视为不需要现在的重要知识和对待。

使用接口常量是一个好的做法。不要因为你喜欢临时的即时编程习惯而制定规则或发布任何法令来反对它。不要以有人不知道如何处理枪支或有滥用枪支倾向的理由来禁止持枪。

我不在乎美国宪法的创始人对它的最初意图是什么。我不关心未写下、未编码的意图。我只关心写下的宪法中的文字表述以及如何利用它们来有效地使社会运作。

我只关心Java语言/平台规范允许我做什么,我打算充分利用它们为我的软件解决方案提供一个高效和有效的媒介。不需要夹克。

使用枚举常量实际上是一种糟糕的做法。它需要编写额外的代码来映射参数到值。Java的创始人没有提供不需要编写映射代码的参数值映射,这表明枚举常量也是对Java语言的不当使用。特别是因为你不被鼓励将参数规范化和组件化,所以会产生一个错误的印象,即混入枚举中的参数属于同一维度。

常量是API的契约。不要忘记这一点。如果你设计和规范化了你的数据模型,并且它们包括常量,那么这些常量就是契约。如果你没有规范化你的数据模型,那么你应该遵守关于如何处理这种坏习惯的限制性编码的法令。

一个奇怪的假设 - 如果接口被无意中实现呢。是的。任何人都可能无意中实现任何接口。没有任何东西能阻止这样的无意识的程序员。

设计和规范化你的数据模型以防止泄露。不要制定限制性法令来保护被认为是导致API中未契约/漏洞参数泄漏的不良实践。解决根本问题,而不是将责任归咎于接口常量。

不使用集成开发环境是一种不良实践。一个正常运作和有效的程序员不是为了证明她能在水下待多久,她能在酷热或潮湿的雷雨天走多远。她是为了使用像汽车、公交车或至少自行车这样的高效工具每天上班走10英里。不要因为你对没有IDE的编程有一种神秘的禁欲迷恋而对其他程序员施加限制。

一些框架旨在帮助程序员继续有效地实践不良习惯。OSGI就是这样一个框架。对接口常量的禁令也是如此。

因此,得出结论...接口常量是一种有效和高效的方式,用于将设计良好和规范化的数据模型组件纳入契约中。在一个适当命名的私有接口嵌套在一个类文件中的接口常量也是一种良好的做法,可以将所有私有常量分组,而不是将它们散布在整个文件中。

所有这些观点都可以在没有开玩笑、讽刺、情感的情况下提出。Stackoverflow不是一个博客平台。

"它需要编写额外的代码来映射参数到值。Java的创始人没有提供不需要编写映射代码的参数值映射,这表明枚举常量也是对Java语言的不当使用。"那么,如果不编写额外的代码,你怎么能得到参数值映射呢?

使用接口常量。完全正确。

枚举常量提供了更多的安全性...一个人可以将一个int字段与任何其他int常量进行比较,例如if (userRole == Consts.MALE)...if (userRole == Consts.US_ZIP_CODE)...,但是使用枚举常量更加安全。

1. 永远不要基于int值比较枚举。2. 从String解析枚举的时间要比哈希映射长得多,所以很多程序员使用String常量而不是枚举。

从String解析枚举哈希映射查找。只有在第一次查询时,当映射被延迟初始化时才会慢。

0
0 Comments

接口常量的用途是什么?

将静态成员放入接口(并实现该接口)是一种不良实践,甚至有一个名字叫做“常量接口反模式”,参见《Effective Java》,第17项:

常量接口模式是接口的一种不良使用。一个类在内部使用一些常量是实现细节。实现常量接口会导致这种实现细节泄露到类的导出API中。对于类的用户来说,类是否实现常量接口并不重要。实际上,这可能会让他们感到困惑。更糟糕的是,这代表了一种承诺:如果在将来的版本中,类被修改以不再需要使用常量,仍然必须实现接口以确保二进制兼容性。如果一个非final类实现了一个常量接口,那么它的所有子类的命名空间将被接口中的常量污染。

Java平台库中有几个常量接口,比如java.io.ObjectStreamConstants。这些接口应该被视为异常情况,不应该模仿。

为了避免常量接口的一些陷阱(因为无法阻止人们实现它),应该优先选择一个具有私有构造函数的合适类(示例来自维基百科):

public final class Constants {
    private Constants() {
        // 限制实例化
    }
    public static final double PI = 3.14159;
    public static final double PLANCK_CONSTANT = 6.62606896e-34;
}

为了在不必使用类名前缀的情况下访问常量(即不必用类名前缀作为前缀),可以使用静态导入(自Java 5以来):

import static Constants.PLANCK_CONSTANT;
import static Constants.PI;
public class Calculations {
    public double getReducedPlanckConstant() {
        return PLANCK_CONSTANT / (2 * PI);
    }
}

好吧,但如果你有一个接口不仅用于常量定义。所以我有一些接口被许多类实现,它包含方法声明,但我也想在其中添加一些常见的值,比如大小。在这种情况下,这真的是一个糟糕的模式吗?我同意只为常量创建接口是反模式的。

对于Android来说呢?在那里使用接口常量可能会很方便,例如在捕获Intent支持的键集合时。尽管我不确定这比仅仅在将使用这些常量的类中定义它们更好多少。

这并不是因为有人在书中这样说就是一件坏事。只要你不实现该接口以获得对这些常量的访问,这是可以的。

意图类中的公共常量是意图API的一部分。在这个问题的背景下,我们正在考虑的是定义一个只包含一堆全局常量以在整个应用程序中使用的接口的问题。如果一组常量在多个类中经常使用,仅在使用它们的类中定义常量将会重复。

不不不。《Effective Java》中的引用是关于其他事情的!创建仅用于保存常量的接口是一个更好的替代方案。《Effective Java》说:“一个类在内部使用一些常量是实现细节”。但这里并非如此。我们正在讨论“全局”常量。谁会想要在其中没有方法声明的接口中实现呢?

我同意ACV的观点。如果常量接口不是导出的API模块的一部分,或者没有地方实现,我不认为存在问题。使用const final类是丑陋的:你需要一个私有构造函数,它只会使代码凌乱,因为它没有用处。

这个答案没有正确地呈现“Effective Java”书中的主要观点,因为它将主要观点放在了括号里:“(并实现该接口)”。相反,它强调了接口中的常量的观点(除非你实现这样的接口,否则是可以接受的)。这个答案并不是完全错误的,因为如果你仔细阅读引用的片段,你就可以看到《Effective Java》的作者最初的意图。但我认为这是误导的。在我看来,“并实现该接口”的部分应该用粗体字强调。

我认为我们都同意,为了获取常量而实现接口是不好的。即使你导入了常量,我认为在某些情况下接口仍然比类稍微差一些,因为你无法强制用户静态导入这些值,而不是扩展接口。而对于具有私有构造函数的最终类,你强制用户做正确的事情。我想这全凭个人喜好:允许用户使用一个反模式vs样板代码(最终类,私有构造函数,需要编写静态常量)。

我同意,但我还会创建一个枚举来表示这些常量,而不是使用具有静态变量的类。原因是枚举提供了某种类型安全性,我还可以扩展这个枚举以像普通类一样运行。在你的例子中,我可以将计算reducedPlanckConstant的过程也放入枚举中,这样一切都保持在一起。

0