用Java实现常量的最佳方法是什么?[关闭]


372

我看过这样的例子:

public class MaxSeconds {
   public static final int MAX_SECONDS = 25;
}

并假设我可以有一个Constants类来包装常量,并声明它们为static final。我几乎不了解Java,并且想知道这是否是创建常量的最佳方法。



Answers:


403

这是完全可以接受的,甚至可能是标准。

(public/private) static final TYPE NAME = VALUE;

TYPE类型NAME是哪里,是所有大写字母的名称,下划线带有空格,并且VALUE是常量值;

我强烈建议不要将常量放在自己的类或接口中。

附带说明:声明为final且可变的变量仍然可以更改;但是,变量永远不能指向其他对象。

例如:

public static final Point ORIGIN = new Point(0,0);

public static void main(String[] args){

    ORIGIN.x = 3;

}

那是合法的,ORIGIN因此指向(3,0)。


19
您甚至可以“导入静态MaxSeconds.MAX_SECONDS;”。这样您就不
必将

23
先前有关导入静态的注释仅适用于Java 5+。有些人认为速记法不值得混淆常量的来源,当读取长代码时,MaxSeconds.MAX_SECONDS可能更容易理解,然后向上看导入。
MetroidFan2002

5
因为您可以像jjnguy所示那样更改objetc,所以最好是将constatns是不可变的对象或只是普通的图元/字符串。
marcospereira

14
如果您正在阅读此问题,请先阅读下面的以下两个答案,然后再认真对待该答案,尽管它被接受还是有争议的。
orbfish 2012年

3
@jjnguy你没有错,但是如果我只读问题和答案的前几行,我会觉得“常数类”是“完全可以接受的,甚至可能是标准”。这个想法错误的。
Zach Lysobey

235

我强烈建议不要使用单个常量类。当时这似乎是个好主意,但是当开发人员拒绝记录常量并且该类增长到包含多达500个完全不相关的常量(与应用程序的完全不同的方面)时,这通常会变成完全不可读的常量文件。代替:

  • 如果可以访问Java 5+,请使用枚举为应用程序区域定义特定的常量。对于这些常量,应用程序区域的所有部分都应引用枚举,而不是常量。您可以声明类似于声明类的枚举。枚举也许是Java 5+的最(也是唯一的)有用的功能。
  • 如果您的常量仅对特定类或其子类之一有效,则将其声明为protected或public,然后将其放在层次结构中的顶级类上。这样,子类可以访问这些常量值(如果其他类通过公共访问它们,则这些常量不仅仅对特定的类有效...这意味着使用此常量的外部类可能与该常量紧密耦合。包含常量的类)
  • 如果您有一个定义了行为的接口,但是返回值或参数值应该是特定的,那么在该接口上定义常量是完全可以接受的,以便其他实现者可以访问它们。但是,请避免创建仅用于保存常量的接口:它可能与仅为保存常量而创建的类一样糟糕。

12
完全同意...这可以证明是大型项目的经典反模式。
达斯

30
脱离主题,但是...泛型肯定不是完美的,但是我认为您可以为Java 5的有用功能提供充分的理由:)
Martin McNulty

3
@ŁukaszL。问题本身实际上是基于观点的(只要出现“最佳”,通常就是观点问题),因此答案是对该问题的有效答案。我给出了关于什么的答案(是的,我相信是的,所以是的,这是一种意见,因为“最佳”会随时间变化,并且通常基于意见)是在Java中实现常量的最佳方法。
MetroidFan2002 2014年

1
上面的选项都没有为您提供真正的全局变量。如果我有一些在各处都使用但不是枚举的东西怎么办?我只做一件事的枚举吗?
markthegrea 2014年

1
如果您需要一个跨所有模块的全局常量,则设计策略可能存在问题。如果您确实需要全局常量,请在顶级程序包中为其设置公共最终类,并将其粘贴在那里。一旦意识到并非所有类实际上都需要该常量,则将其删除,然后将其移至最引用该常量的包中。您可以共享整个包恒定的,但它是一个代码味道,要求全局常量,它不是一个枚举类型,枚举类型可以有行为,但一个字符串是一个字符串,一个int是一个int,等等
MetroidFan2002

120

这是一个坏习惯使用的界面,以保持常量(命名常量接口模式由乔希布洛赫)。这是乔希的建议:

如果常量与现有的类或接口紧密关联,则应将其添加到类或接口。例如,所有装箱的数值基元类(例如Integer和Double)都将导出MIN_VALUE和MAX_VALUE常量。如果最好将常量视为枚举类型的成员,则应使用枚举 类型将其导出。否则,应使用不可实例化的实用程序类导出常量。

例:

// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
    private PhysicalConstants() { }  // Prevents instantiation

    public static final double AVOGADROS_NUMBER   = 6.02214199e23;
    public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    public static final double ELECTRON_MASS      = 9.10938188e-31;
}

关于命名约定:

按照惯例,此类字段的名称由大写字母组成,单词之间用下划线分隔。这些字段包含原始值或对不可变对象的引用至关重要。


23
如果您要说一些不好的做法,也许您应该解释一下为什么会这样?
GlennS

14
这是一篇旧文章,但最好abstract在类中使用表示法,而不要使用私有构造函数。
Xtreme Biker

5
马特(Matt),尽管骑自行车的人的建议不是错误的,但我主张提倡最终课程,而非抽象课程。骑自行车的人的观点是,您要确保常量类不可更改。因此,通过将其标记为final,您不允许其被子类化或实例化。这也有助于封装其静态功能,并且不允许其他开发人员对其进行子类化,使其无法完成其设计工作。
liltitus13年

7
@XtremeBiker标记类abstract而不是私有构造函数并不能完全阻止实例化,因为可以将其子类化并实例化子类(这样做不是一个好主意,但有可能)。@ToolmakerSteve不能使用私有构造函数对类进行子类化(至少在没有严重的黑手的情况下也不能这样),因为子类的构造函数需要调用其超类的(现在是私有的)构造函数。因此,标记它final是不必要的(但可能更明确)。
导入

3
仅仅使用类来保存常量甚至更糟。如果您从不想创建该类的对象,为什么首先要使用常规
MaxZoom 2015年


21

只是避免使用接口:

public interface MyConstants {
    String CONSTANT_ONE = "foo";
}

public class NeddsConstant implements MyConstants {

}

这很诱人,但是违反了封装并且模糊了类定义的区分。


1
确实,静态进口是可取的。
亚伦·曼帕

1
这种做法是接口的一种奇怪用法,该接口旨在声明类提供的服务。
拉法罗梅罗2014年

1
我不是不同意避免将接口用于常量,但是我认为您的示例具有误导性。您无需实现接口即可访问常量,因为其隐式静态,公共和最终。因此,它比您在此描述的要简单。
djangofan '17

没错...违反了封装,我更喜欢使用最终的Constant类该类看起来更面向对象,并且比接口OR enum可取注意:如果不需要Android,可以避免枚举。
CoDe17年

19

我使用以下方法:

public final class Constants {
  public final class File {
    public static final int MIN_ROWS = 1;
    public static final int MAX_ROWS = 1000;

    private File() {}
  }

  public final class DB {
    public static final String name = "oups";

    public final class Connection {
      public static final String URL = "jdbc:tra-ta-ta";
      public static final String USER = "testUser";
      public static final String PASSWORD = "testPassword";

      private Connection() {}
    }

    private DB() {}
  }

  private Constants() {}
}

比起,例如,我Constants.DB.Connection.URL用来获得常数。对我来说,它看起来更“面向对象”。


4
有趣,但麻烦。您为什么不按照其他人的建议在与它们最紧密相关的类中创建常量呢?例如,在其他地方的数据库代码中,您是否具有用于连接的基类?例如“ ConnectionBase”。然后,您可以在其中放置常量。任何用于连接的代码都可能已经导入,因此可以简单地说“ ConnectionBase.URL”而不是“ Constants.DB.Connection.URL”。
ToolmakerSteve 2014年

3
@ToolmakerSteve但是,多个类可以使用的常规常量呢?例如样式,Web服务网址等?
Daniel Gomez Rico

将所有常量归为一类具有一项优势-维护。您总是确切地知道在哪里可以找到常量。我并不是说这会使这项技术变得更好,我只是提供了一个优势。@ albus.ua所做的就是对他的常量进行分类,这是一个很好的主意,尤其是在常量类包含许多常量值的情况下。此技术将有助于使类易于管理,并有助于更好地描述常量的目的。
Nelda.techspiress

17

在单独的类中创建静态最终常量会给您带来麻烦。Java编译器实际上将对此进行优化,并将常量的实际值放入引用该常量的任何类中。

如果以后更改'Constants'类,并且不对引用该类的其他类进行硬重新编译,则会使用新旧值的组合。

与其将它们视为常量,不如将它们视为配置参数并创建一个类来管理它们。将值设为非最终值,甚至考虑使用吸气剂。将来,当您确定其中某些参数实际上应由用户或管理员配置时,它将变得更加容易。


+1是对这个极好的警告。(如果不能保证它是一个永久常量,则应考虑使用getter,如big_peanut_horse所述。)顺便说一下,C#中的const同样适用:msdn.microsoft.com/en-us/library/e6w8fe1b.aspx
Jon Coombs 2014年

13

您可能犯的第一个错误是创建一个以通用名称调用的全局可访问类,例如常量。这简直是​​乱七八糟,到处都是垃圾,您失去了找出系统的哪些部分使用这些常量的全部能力。

相反,常量应该进入“拥有”它们的类。您是否有一个名为TIMEOUT的常量?它可能应该进入您的Communications()或Connection()类。MAX_BAD_LOGINS_PER_HOUR?进入User()。等等等等。

另一个可能的用途是Java .properties文件,当可以在运行时定义“常量”,但用户不容易更改它们时。您可以将它们打包到您的.jar中,并使用class resourceLoader引用它们。


当然,您永远都不想从多个类中访问常量,或者避免在类的顶部出现混乱。
orbfish

6

这是正确的方法。

通常,常量不可保存在单独的“常量”类中,因为它们是不可发现的。如果该常量与当前类相关,则将其保留在该位置有助于下一个开发人员。



5

我更喜欢使用getter而不是常量。这些吸气剂可能返回常数值,例如public int getMaxConnections() {return 10;},但是任何需要该常量的东西都会经过吸气剂。

好处之一是,如果您的程序超出了常量,就会发现该常量必须是可配置的,您只需更改getter返回常量的方式即可。

另一个好处是,为了修改常量,您不必重新编译使用该常量的所有内容。当您引用静态final字段时,该常量的值将编译为引用该常量的任何字节码。


5
很好地重新编译引用类在21世纪几乎不是负担。而且,除了访问和更改成员变量之外,您永远不要将访问器/更改器(getter / setter)模型用于其他目的。从概念上讲,常数本质上是指立即数,而(同时)getter / setter则是指管理状态。此外,您只是在要求混乱:人们不会期望吸气剂产生的仅仅是常数。

5

我同意使用接口不是解决之道。避免这种模式甚至在Bloch的Effective Java中有其自己的项目(#18)。

Bloch与常量接口模式相对的一个论点是,使用常量是实现细节,但是实现使用它们的接口会在导出的API中公开该实现细节。

public|private static final TYPE NAME = VALUE;模式是声明不变的好方法。就个人而言,我认为最好避免创建单独的类来容纳所有常量,但是除了个人喜好和风格之外,我从未见过不这样做的理由。

如果您的常量可以很好地建模为枚举,请考虑枚举 1.5或更高版本中可用结构。

如果您使用的版本早于1.5,仍然可以使用常规Java类提取类型安全的枚举。(有关更多信息,请参见本网站)。


某些常量可用于调用API。例如,请参见接口org.springframework.transaction.TransactionDefinition。它有一个常量列表,例如int PROPAGATION_REQUIRED = 0;
borjab 2015年

我知道这很旧,但是到Bloch的Effective Java的链接已断开。您能否提供另一个或另一个参考来支持“使用接口是行不通的”?
Nelda.techspiress

4

基于以上评论,我认为这是一种将老式的全局常量类(具有公共静态最终变量)更改为类似于枚举的等效方法,如下所示:

public class Constants {

    private Constants() {
        throw new AssertionError();
    }

    public interface ConstantType {}

    public enum StringConstant implements ConstantType {
        DB_HOST("localhost");
        // other String constants come here

        private String value;
        private StringConstant(String value) {
            this.value = value;
        }
        public String value() {
            return value;
        }
    }

    public enum IntConstant implements ConstantType {
        DB_PORT(3128), 
        MAX_PAGE_SIZE(100);
        // other int constants come here

        private int value;
        private IntConstant(int value) {
            this.value = value;
        }
        public int value() {
            return value;
        }
    }

    public enum SimpleConstant implements ConstantType {
        STATE_INIT,
        STATE_START,
        STATE_END;
    }

}

因此,我可以将它们推荐为:

Constants.StringConstant.DB_HOST

4
为什么?那有什么改善?现在每个引用都很麻烦(Constants.StringConstant.whatever)。恕我直言,您在这里要走在崎bump不平的道路上。
ToolmakerSteve


2

有一定的意见可以回答这个问题。首先,java中的常量通常被声明为public,static和final。原因如下:

public, so that they are accessible from everywhere
static, so that they can be accessed without any instance. Since they are constants it
  makes little sense to duplicate them for every object.
final, since they should not be allowed to change

我绝不会仅仅因为通常期望实现接口而将接口用于CONSTANTS访问器/对象。这看起来不好笑吗:

String myConstant = IMyInterface.CONSTANTX;

相反,我会根据一些小的取舍,在几种不同的方法之间进行选择,因此这取决于您的需求:

1.  Use a regular enum with a default/private constructor. Most people would define 
     constants this way, IMHO.
  - drawback: cannot effectively Javadoc each constant member
  - advantage: var members are implicitly public, static, and final
  - advantage: type-safe
  - provides "a limited constructor" in a special way that only takes args which match
     predefined 'public static final' keys, thus limiting what you can pass to the
     constructor

2.  Use a altered enum WITHOUT a constructor, having all variables defined with 
     prefixed 'public static final' .
  - looks funny just having a floating semi-colon in the code
  - advantage: you can JavaDoc each variable with an explanation
  - drawback: you still have to put explicit 'public static final' before each variable
  - drawback: not type-safe
  - no 'limited constructor'

3.  Use a Class with a private constructor:
  - advantage: you can JavaDoc each variable with an explanation
  - drawback: you have to put explicit 'public static final' before each variable
  - you have the option of having a constructor to create an instance
     of the class if you want to provide additional functions related
     to your constants 
     (or just keep the constructor private)
  - drawback: not type-safe

4. Using interface:
  - advantage: you can JavaDoc each variable with an explanation
  - advantage: var members are implicitly 'public static final'
  - you are able to define default interface methods if you want to provide additional
     functions related to your constants (only if you implement the interface)
  - drawback: not type-safe

2

用Java实现常量的最佳方法是什么?

我们应该避免的一种方法是:使用接口定义常量。

创建专门声明常量的接口确实是最糟糕的事情:它打破了设计接口的原因:定义方法契约。

即使已经存在满足特定需求的接口,在常量中声明常量也确实没有意义,因为常量不应该成为API和提供给客户端类的协定的一部分。


为简化起见,我们大致有4种有效的方法

搭配static final String/Integer栏位:

  • 1)使用一个不仅在内部声明常量的类。
  • 1个变体)创建一个仅用于声明常量的类。

Java 5 enum

  • 2)在相关目的类(例如嵌套类)中声明枚举。
  • 2变体)将枚举创建为独立类(因此在其自己的类文件中定义)。

TLDR:哪种方法最好,在哪里可以找到常量?

在大多数情况下,枚举方法可能比该static final String/Integer方法更好,我个人认为static final String/Integer只有在我们有充分理由不使用枚举的情况下才应使用该方法。
关于应该在何处声明常数值,其思想是搜索是否存在单个类,该类具有特定且强大的具有常数值的功能凝聚力。如果找到这样的类,则应将其用作常量所有者。否则,该常数不应与任何特定类相关联。


static final String/ static final Integerenum

枚举的使用确实是一种值得深思的方法。
枚举在字段StringInteger常量字段上都具有很大的优势。
他们设置了更强的编译约束。如果定义一个将枚举作为参数的方法,则只能传递在枚举类中定义的枚举值(或null)。
使用String和Integer,您可以用兼容类型的任何值替换它们,即使该值不是static final String/ static final Integer字段中定义的常量,编译也可以。

例如,在类中定义为static final String字段的两个常量以下:

public class MyClass{

   public static final String ONE_CONSTANT = "value";
   public static final String ANOTHER_CONSTANT = "other value";
   . . .
}

这里的方法期望将这些常量之一作为参数:

public void process(String constantExpected){
    ...    
}

您可以通过以下方式调用它:

process(MyClass.ONE_CONSTANT);

要么

process(MyClass.ANOTHER_CONSTANT);

但是没有编译约束可以阻止您以这种方式调用它:

process("a not defined constant value");

仅在运行时且仅一次检查传输的值时才会出现错误。

使用枚举时,不需要检查,因为客户端只能在枚举参数中传递枚举值。

例如,在枚举类中定义了两个值(即开箱即用的常量):

public enum MyEnum {

    ONE_CONSTANT("value"), ANOTHER_CONSTANT(" another value");

    private String value;

    MyEnum(String value) {
       this.value = value;
    }
         ...
}

这里的方法期望将这些枚举值之一作为参数:

public void process(MyEnum myEnum){
    ...    
}

您可以通过以下方式调用它:

process(MyEnum.ONE_CONSTANT);

要么

process(MyEnum.ANOTHER_CONSTANT);

但是编译永远不会允许您以这种方式调用它:

process("a not defined constant value");

我们应该在哪里声明常数?

如果您的应用程序包含单个现有类,且该类具有特定且强大的功能且具有恒定值,则1)和2)显得更直观。
通常,如果在操作它们的主类中声明了这些常量,或者使用了很自然的名称来猜测我们将在其中找到常量,则可以简化常量的使用。

例如,在JDK库中,指数和pi常数值是在不仅声明常数声明(java.lang.Math)的类中声明的。

   public final class Math {
          ...
       public static final double E = 2.7182818284590452354;
       public static final double PI = 3.14159265358979323846;
         ...
   }

使用数学功能的客户通常依赖于Math该类。因此,他们可能会发现常量很轻松了,也可以记住EPI以非常自然的方式进行定义。

如果您的应用程序不包含具有非常特定且强大的功能且具有恒定值的现有类的现有类,则1变体和2变体的方式会更直观。
通常,如果常量在一个操作它们的类中声明,而我们还有3或4个其他对它们进行尽可能多的操作的类,并且这些常量中没有一个比其他的更自然,那么使用常量就不会容易主机常数值。
在这里,定义一个自定义类仅包含常量值是有意义的。
例如,在JDK库中,java.util.concurrent.TimeUnit没有在一个特定的类中声明该枚举,因为实际上并没有一个,只有一个JDK特定的类看起来是最直观的持有它:

public enum TimeUnit {
    NANOSECONDS {
      .....
    },
    MICROSECONDS {
      .....
    },
    MILLISECONDS {
      .....
    },
    SECONDS {
      .....
    },
      .....
}      

许多类中声明java.util.concurrent使用它们: BlockingQueueArrayBlockingQueue<E>CompletableFutureExecutorService,...确实没有他们中的一个似乎更适合持有枚举。


1

可以通过在类内创建一个不可变属性(即带有final修饰符的成员变量)来声明任何类型的常量。通常,还会提供staticpublic修饰符。

public class OfficePrinter {
    public static final String STATE = "Ready";  
}

在许多应用中,常量的值指示从n个元组(例如,枚举)中进行选择。在我们的示例中,我们可以选择定义一个枚举类型,该类型将限制可能的赋值(即改进的类型安全性):

public class OfficePrinter {
    public enum PrinterState { Ready, PCLoadLetter, OutOfToner, Offline };
    public static final PrinterState STATE = PrinterState.Ready;
}

1

一个通用的常量类是一个坏主意。常量应该与逻辑上最相关的类组合在一起。

建议不要使用任何类型的变量(尤其是枚举),而应使用方法。创建一个与变量名称相同的方法,并使其返回您分配给变量的值。现在删除该变量,并用对您刚刚创建的方法的调用替换对它的所有引用。如果您觉得常量足够通用,就不必为了使用它而创建类的实例,那么可以将常量方法设为类方法。


1

FWIW,以秒为单位的超时值可能应该是配置设置(从属性文件或通过Spring注入通过读取),而不是常量。


1

有什么区别

1。

public interface MyGlobalConstants {
    public static final int TIMEOUT_IN_SECS = 25;
}

2。

public class MyGlobalConstants {
    private MyGlobalConstants () {} // Prevents instantiation
    public static final int TIMEOUT_IN_SECS = 25;
}

MyGlobalConstants.TIMEOUT_IN_SECS在需要此常量的任何地方使用 。我认为两者都一样。


1
这似乎是对宾科布给出的答案的一种评论。我认为它们的行为非常相似,但是bincob的观点是它们没有以任何方式定义接口。建议是将常量添加到实型类,而不是创建MyGlobalConstants骨架类。(尽管这偶尔是有道理的;可以通过使用静态常量和私有构造函数来防止实例化来使用“静态类”;请参阅java.lang.math。)考虑使用枚举。
乔恩·库姆斯

同样在类声明中加上“ final”将防止子类化。(在C#中,您可以执行“静态”,这意味着“最终摘要”,因此不需要显式的私有构造函数。)
Jon Coombs 2014年

是的,@ JonCoombs但“最终”并不能阻止其直接实例化。Java不允许最终类和抽象类同时出现在类中,因此,出现了无休止的私有构造函数,以防止实例化和子类化。我不知道为什么不允许使用“最终摘要”,除了乍看之下它看起来是矛盾的:“您不能子类化,但该类应该被子类化”。

0

我不会称该类与常量相同(除了大小写)……我至少会拥有一类“设置”,“值”或“常量”,所有常量都将存在。如果我有很多,则将它们分组为逻辑常量类(UserSettings,AppSettings等)。


我打算做一个叫做Constants的类,这只是我发现的一个小例子。
mk。

0

要更进一步,可以将全局使用的常量放置在接口中,以便可以在系统范围内使用它们。例如

public interface MyGlobalConstants {
    public static final int TIMEOUT_IN_SECS = 25;
}

但是请不要实施它。通过完全限定的类名直接在代码中引用它们。


在接口中声明它们(而不是实现它)的意义在于,您可能会错过“ public static final”。
汤姆·霍顿-大头钉

9
接口用于定义行为契约,而不是用于保持常量的便捷机制。
约翰·托普利

@JohnTopley是的,但是有效。;)
trusktr

0

对于常量,枚举是恕我直言的更好选择。这是一个例子

公共类myClass {

public enum myEnum {
    Option1("String1", 2), 
    Option2("String2", 2) 
    ;
    String str;
            int i;

            myEnum(String str1, int i1) { this.str = str1 ; this.i1 = i }


}

0

我这样做的一种方式是通过使用常量值创建一个'Global'类,并在需要访问该常量的类中进行静态导入。


0

static final是我的偏爱,enum如果项目确实是可枚举的,我只会使用。


0

我用 static final用来声明常量,并使用ALL_CAPS命名符号。我已经看到了很多现实生活中的实例,其中所有常量都捆绑在一起形成一个接口。一些帖子正确地将其称为不好的做法,主要是因为这不是接口的用途。接口应强制执行合同,并且不应放置无关的常量。如果常量的语义不属于特定的类,则将其放到无法实例化(通过私有构造函数)的类中也可以。 es)。我总是在与它最相关的类中放置一个常量,因为这很有意义并且也易于维护。

枚举是表示一个值范围的不错选择,但是如果您要存储独立常量,并且强调绝对值(例如TIMEOUT = 100 ms),则可以采用该static final方法。


0

我同意大多数人的说法,在处理常量集合时最好使用枚举。但是,如果您使用Android进行编程,则有更好的解决方案:IntDef Annotation

@Retention(SOURCE)
@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST,NAVIGATION_MODE_TABS})
public @interface NavigationMode {}
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
...
public abstract void setNavigationMode(@NavigationMode int mode);
@NavigationMode
public abstract int getNavigationMode();

IntDef注释以一种简单的方式优于枚举,因为它只是一个编译时标记,所以占用的空间要少得多。它不是一个类,也不具有自动字符串转换属性。


虽然我同意不单独在Java中使用接口并避免在Android中使用枚举的最佳做法,但仅当您使用少量字段时,Android中的这种替换才有效。这可以节省大量内存,但是由于您是混合枚举中每个字段的接口,因此可能导致膨胀。例如,如果我有一个混合的枚举定义了对象在其构造函数中的作用,则无法使用此方法保存任何内容,而是返回非类型安全常量,因为在Android中,您不需要太多的类/接口。
Droid Teahouse,

0

引用约书亚·布洛赫(Joshua Bloch)却不了解基本的零基础原教旨主义,这是一种不良习惯和令人讨厌的做法

我什么都没读,约书亚·布洛赫(Joshua Bloch)

  • 他是一个可怕的程序员
  • 或到目前为止,我发现引用他的人(约书亚是我假设的男孩的名字)只是使用他的材料作为宗教文字来证明他们对软件的宗教纵容。

就像圣经中的原教旨主义一样,所有圣经定律都可以用

  • 全心全意地爱着基本身份
  • 爱邻居如己

因此,类似地,软件工程原教旨主义可以归纳为

  • 专心致志地致力于基础零基础
  • 并像您自己一样致力于您的程序员的卓越成就。

此外,在圣经的原教旨主义者圈子中,得出了强有力而合理的推论。

  • 首先爱自己。因为如果您不爱自己,那么“爱自己就像自己的邻居”这个概念就没有太大的意义,因为“您有多爱自己”是您要爱别人的基准线。

同样,如果您不尊重自己作为程序员,而只是接受某些编程大师的声明和预言而又不质疑基础知识,那么您对Joshua Bloch(等等)的引用和依赖是毫无意义的。因此,您实际上不会尊重您的程序员。

软件编程的基本定律

  • 懒惰是优秀程序员的美德
  • 您将使您的编程生活变得轻松,懒惰并因此尽可能有效
  • 对于与您一起工作并接手您的编程工作的neigbour-程序员,您将使编程的后果和工作尽可能轻松,懒惰,并因此尽可能有效。

接口模式常量是个坏习惯

根据什么根本有效和负责任的编程法则,该宗教法令应属于哪些法律?

只需阅读有关接口模式常量的Wikipedia文章(https://en.wikipedia.org/wiki/Constant_interface),愚蠢的借口就针对接口模式常量声明了这种说法。

  • 如果没有IDE?作为软件程序员,到底谁会不使用IDE?我们大多数人都是程序员,他们更愿意不必为了避免使用IDE而证明自己具有男子气概的生存主义主义。

    • 另外-等待微功能编程的第二个拥护者,以作为不需要IDE的一种手段。等到您阅读我对数据模型规范化的解释。
  • 使用当前范围内未使用的变量污染名称空间?可能是这种观点的支持者

    • 不了解数据模型规范化,也不需要数据模型规范化
  • 使用接口强制执行常量会滥用接口。支持者有这样的坏习惯

    • 没有看到“常量”必须被视为合同。接口用于强制执行或预测对合同的遵守情况。
  • 将来,即使不是不可能,将接口转换为已实现的类也是很困难的。哈....嗯... ???

    • 您为什么要从事诸如维持生计这样的编程方式?哎呀,为什么要献身于这样的氛围和不良的编程习惯?

无论有什么借口,在根本有效的软件工程中对接口常数进行合法化或普遍不鼓励使用时,都没有合法的借口。

制定《美国宪法》的开国元勋的初衷和心理状态并不重要。我们可以辩论开国元勋的初衷,但我所关心的只是美国宪法的书面声明。每个美国公民都有责任利用书面的文学原教旨主义而非美国宪法的非书面的创始意图。

同样,我不在乎Java平台和编程语言的创始人对于接口的“原始”意图。我关心的是Java规范提供的有效功能,并且我打算充分利用这些功能,以帮助我实现负责任的软件编程的基本定律。我不在乎是否被认为“违反了界面的意图”。我不在乎Gosling或Bloch所说的“正确使用Java的方式”,除非他们所说的不违反我对有效实现基本原理的需求。

基本是数据模型规范化

数据模型的托管或传输方式无关紧要。如果您不了解数据模型规范化的需求和过程,则无论是使用接口,枚举或其他任何东西,关系式SQL还是无SQL。

我们必须首先定义并标准化一组流程的数据模型。而且,当我们拥有一致的数据模型时,我们只能使用其组件的流程来定义功能行为,并限制应用程序的领域或领域。只有这样,我们才能定义每个功能过程的API。

甚至EF Codd提出的数据标准化方面也受到了严峻挑战和严峻挑战。例如,他对1NF的声明被批评为含糊,不统一和过于简化,尤其是在现代数据服务,回购技术和传输出现时,他的其余声明也受到批评。IMO,应该完全放弃EF Codd语句,并设计一套在数学上更合理的新语句。

EF Codd的一个明显缺陷及其导致无法有效地理解人类的原因是他相信可以通过一系列零散的二维映射来有效地感知人类可感知的多维可变维度数据。

数据规范化的基础

EF Codd无法表达的内容。

在每个一致性数据模型中,这些是要实现的数据模型一致性的顺序分级顺序。

  1. 数据实例的统一性和身份。
    • 设计每个数据组件的粒度,从而使它们的粒度处于可以唯一标识和检索组件的每个实例的级别。
    • 没有实例别名。就是说,没有一种方法可以使一个标识产生一个以上的组件实例。
  2. 缺少实例串扰。不需要使用组件的一个或多个其他实例来帮助标识组件的实例。
  3. 数据组件/维度的统一性和一致性。
    • 存在组件去混叠。必须存在一个定义,以便可以唯一地标识组件/尺寸。这是组件的主要定义;
    • 主要定义不会导致暴露不属于预期组成部分的子维度或成员组成部分的情况;
  4. 组件脱碳的独特方法。一个组件必须存在一个,只有一个这样的组件去混叠定义。
  5. 在组件的层次关系中,只有一个定义接口或协定可以标识父组件。
  6. 组件串扰不存在。不必使用另一个组件的成员来帮助确定一个组件。
    • 在这样的亲子关系中,对父母的识别定义不得取决于孩子的一部分成员组成部分。父母身份的成员组成部分必须是完整的孩子身份,而不能求助于孩子的任何或所有孩子。
  7. 抢占数据模型的双峰或多峰外观。
    • 当存在组件的两个候选定义时,很明显的迹象是存在两个不同的数据模型被混合为一个。这意味着在数据模型级别或字段级别存在不一致性。
    • 应用程序领域必须一致地使用一个且仅一个数据模型。
  8. 检测并识别组件突变。除非您对海量数据进行了统计成分分析,否则您可能看不到或看不到需要处理成分突变。
    • 数据模型的某些组件可能会周期性或逐渐发生变异。
    • 该模式可以是成员旋转或换位旋转。
    • 成员轮换突变可能是子组件之间不同的子组件交换。或者必须定义全新的组件。
    • 换位突变将表现为维成员变异为属性,反之亦然。
    • 必须将每个突变周期标识为不同的数据模式。
  9. 对每个突变进行版本化。这样,当可能需要处理数据模型的8年历史突变时,您可以提取出数据模型的先前版本。

在互服务组件应用程序的领域或网格中,必须只有一个并且只有一个一致的数据模型,或者存在一种用于数据模型/版本标识自身的方法。

我们还在询问是否可以使用接口常量吗?真的吗

数据标准化问题比这个平凡的问题更为紧要。如果您不解决这些问题,那么您认为接口常数引起的混乱就相对没有了。齐尔奇

然后根据数据模型规范化,将组件确定为变量,属性,合同接口常数。

然后确定哪个值注入,属性配置占位,接口,最终字符串等。

如果您不得不以需要定位组件为借口,以更容易根据接口常数来指示借口,则意味着您习惯于不练习数据模型规范化。

也许您希望将数据模型编译为vcs版本。您可以提取数据模型的一个明显可识别的版本。

完全确保在接口中定义的值是不可变的。和共享。当您只需要一组常量时,为什么要从另一个类中将一组最终字符串加载到您的类中?

那么,为什么不发布数据模型合同呢?我的意思是,如果您可以连贯地进行管理和规范化,为什么不呢?...

public interface CustomerService {
  public interface Label{
    char AssignmentCharacter = ':';
    public interface Address{
      String Street = "Street";
      String Unit= "Unit/Suite";
      String Municipal = "City";
      String County = "County";
      String Provincial = "State";
      String PostalCode = "Zip"
    }

    public interface Person {
      public interface NameParts{
        String Given = "First/Given name"
        String Auxiliary = "Middle initial"
        String Family = "Last name"
      }
    }
  }
}

现在,我可以通过以下方式引用应用的合同规定的标签:

CustomerService.Label.Address.Street
CustomerService.Label.Person.NameParts.Family

这混淆了jar文件的内容?作为Java程序员,我不在乎jar的结构。

这给以osgi为动力的运行时交换带来了复杂性。Osgi是允许程序员继续养成不良习惯的极为有效的手段。有比osgi更好的选择。

还是为什么不呢?私有常量不会泄漏到已发布的合同中。所有私有常量都应归入名为“ Constants”的私有接口中,因为我不想搜索常量,而且我懒于重复输入“ private final String”。

public class PurchaseRequest {
  private interface Constants{
    String INTERESTINGName = "Interesting Name";
    String OFFICIALLanguage = "Official Language"
    int MAXNames = 9;
  }
}

也许甚至这个:

public interface PurchaseOrderConstants {
  public interface Properties{
    default String InterestingName(){
       return something();
    }
    String OFFICIALLanguage = "Official Language"
    int MAXNames = 9;
  }
}

值得考虑的唯一的接口常量问题是何时实现接口。

这不是接口的“原始意图”吗?就像我会关心开国元勋在制定《美国宪法》时的“原始意图”一样,而不是最高法院将如何解释《美国宪法》的书面文字?

毕竟,我生活在自由,荒野和勇敢者之乡的土地上。勇敢,自由,疯狂-使用界面。如果我的程序员程序员拒绝使用高效且懒惰的编程方式,那么我是否有遵守黄金法则的义务,那就是降低我的编程效率以适应他们的编程习惯?也许我应该这样做,但这不是理想的情况。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.