Java的通用类型参数命名约定(带有多个字符)?

cha*_*r29 117 java generics naming-conventions

在我写的一些接口中,我想用多个字符命名泛型类型参数,以使代码更具可读性.

就像是....

Map<Key,Value>
Run Code Online (Sandbox Code Playgroud)

而不是......

Map<K,V>
Run Code Online (Sandbox Code Playgroud)

但是当涉及到方法时,类型参数看起来像java-classes,这也令人困惑.

public void put(Key key, Value value)
Run Code Online (Sandbox Code Playgroud)

这看起来像Key和Value是类.我发现或想到了一些符号,但没有像Sun的惯例或一般的最佳实践.

我猜测或发现的替代品......

Map<KEY,VALUE>
Map<TKey,TValue>
Run Code Online (Sandbox Code Playgroud)

Bal*_*usC 174

Oracle在Java Tutorials> Generics> Generic Types中推荐以下内容:

键入参数命名约定

按照惯例,类型参数名称是单个大写字母.这与您已经了解的变量命名约定形成鲜明对比,并且有充分的理由:如果没有这种约定,就很难区分类型变量和普通类或接口名称.

最常用的类型参数名称是:

  • E - Element(Java Collections Framework广泛使用)
  • K - 钥匙
  • N - 数字
  • T型
  • V - 价值
  • S,U,V等 - 第2,第3,第4类型

您将在整个Java SE API和本课程的其余部分中看到这些名称.

我坚持这样做是为了避免开发人员和可能的维护者之间的混淆.

  • Blech,单字母命名.我遵循这个惯例,因为惯例比描述性名称更重要,但令人遗憾的是,这是他们想出的最好的. (26认同)
  • 新的流框架也使用`R`表示结果,使用`A`表示累加器. (13认同)
  • @warbaker:我觉得这是区分参数化类型和实际类的好方法.你怎么会告诉我们`List <Element>`中的`Element`是参数化类型还是类? (4认同)
  • 为什么要担心区分参数化类型和实际类?他们*是*班级.无论如何,你必须在文件中的某处向上滚动以找出它们被定义为什么.它既可以是导入类型,也可以是参数化类型. (4认同)
  • 它看起来不像`BiFunction&lt;T, U, R&gt;` 遵循这个约定。如果是这样,它将是`BiFunction&lt;T, S, R&gt;`。 (2认同)

Bas*_*que 42

附加 Type

可以在DZone页面的参数化类型命名约定的注释中找到一个很好的讨论.

请参阅Erwin Mueller的评论.他的建议对我来说非常明显:附加一句话Type.

叫苹果是苹果,车是汽车.有问题的名称是数据类型的名称,对吧?(在OOP中,类本质上定义了一种新的数据类型.)因此将其称为"类型".

穆勒的例子,来自原帖的文章:

public interface ResourceAccessor <ResourceType, ArgumentType, ResultType> {
    public ResultType run (ResourceType resource, ArgumentType argument);
}
Run Code Online (Sandbox Code Playgroud)

附加 T

一个重复的问题由Andy Thomas 提供此答案.请注意Google风格指南中的摘录,其中建议多字符类型名称应以单个大写形式结尾T.

  • 我喜欢这个答案。添加“类型”非常清晰,可以让您拥有描述性名称。我厌倦了人们说“这样做是因为这是惯例”,没有其他理由。如果这是一个糟糕的惯例,也许我们需要一个新的。 (3认同)
  • 简单地附加后缀“Type”的一个问题是它也被用作许多类名的后缀——甚至在标准 Java 库中也是如此。乍一看并不清楚它是类型参数而不是类名。 (2认同)

And*_*mas 16

是的,您可以对类型变量使用多字符名称,只要它们与类名明确区分即可.

这与Sun在2004年引入仿制药时提出的惯例不同.但是:

  • 存在多个惯例.
  • 多字符名称与其他Java样式一致,例如Google的 Java样式.
  • 可读的名字(惊喜!)更具可读性.

可读性

在我写的一些接口中,我想用多个字符命名泛型类型参数,以使代码更具可读性.

可读性很好.

相比:

    public final class EventProducer<L extends IEventListener<E>,E> 
            implements IEventProducer<L,E> {
Run Code Online (Sandbox Code Playgroud)

至:

    public final class EventProducer<LISTENER extends IEventListener<EVENT>,EVENT> 
           implements IEventProducer<LISTENER, EVENT> {
Run Code Online (Sandbox Code Playgroud)

或者,使用Google的多字符约定:

    public final class EventProducer<ListenerT extends IEventListener<EventT>,EventT> 
           implements IEventProducer<ListenerT, EventT> {

    public final class EventProducer<ListenerT extends IEventListener<EventT>,EventT> 
           implements IEventProducer<ListenerT, EventT> {
Run Code Online (Sandbox Code Playgroud)

谷歌风格

谷歌的Java风格指南允许单字母名称和多字符类的名字一样在T.结束

5.2.8输入变量名称

每个类型变量都以两种样式之一命名:

  • 单个大写字母,任选随后用单个数字(例如E,T,X,T2)

  • 用于类的形式的名称(参见第5.2.2节,类名),后跟大写字母T(示例:RequestT,FooBarT).

问题

"如果没有这种约定,就很难区分类型变量和普通类或接口名称." - 来自Oracle教程,"通用类型"

单字符名称不是区分类型参数和类名的唯一方法,如上所述.

为什么不直接记录JavaDoc中的类型参数?

确实,@paramJavaDoc元素可以提供更长的描述.但是,JavaDocs也不一定是可见的.(例如,Eclipse中有一个显示类型参数名称的内容辅助.)

多字符类型参数名称不符合Oracle约定!

Sun的许多原始约定几乎普遍遵循Java编程.

但是,这个特殊的惯例不是.

竞争公约中的最佳选择是意见问题.在这种情况下,选择Oracle以外的约定的后果很小.您和您的团队可以选择最符合您需求的会议.


Tom*_*rae 15

您可以使用javadoc至少为您的泛型类的用户提供线索.我仍然不喜欢它(我同意@ chaper29),但文档有帮助.

例如,

/**
 * 
 * @param <R> - row
 * @param <C> - column
 * @param <E> - cell element
 */
public class GenericTable<R, C, E> {

}
Run Code Online (Sandbox Code Playgroud)

我所知道的另一件事是使用我的IDE来重构违反约定的类.然后处理代码并重构为单个字母.如果使用许多类型参数,无论如何都会使我更容易.

  • 我想说类型参数的 Javadoc 注释通常是必须的。 (2认同)

Voj*_*cka 15

为什么原因正式命名约定 reccommends使用单字母如下:

如果没有这种约定,就很难区分类型变量和普通类或接口名称.

我认为在现代IDE中,理性不再有效,例如.IntelliJ Idea显示具有与常规类不同颜色的泛型类型参数.

IntelliJ Idea 2016.1中显示的具有泛型类型的代码 IntelliJ Idea 2016.1中显示的具有泛型类型的代码

由于这种区别,我使用更长的描述性名称作为我的泛型类型,具有与常规类型相同的约定.我避免添加前缀和后缀,如T或Type,因为我认为它们是不必要的噪音,不再需要在视觉上区分泛型类型.

注意:由于我不是Eclipse或Netbeans的用户,我不知道他们是否提供了similliar功能.