关于这个问题的对话似乎是关于命名和类的对话的对立面。我发现这令人震惊,并认为这个决定比简单地选择一个命名约定并始终使用它要深入得多。interface
abstract
static final
抽象和接口
在命名接口和抽象类时,公认的约定已经演变为不以 your 或 name 作为前缀或后缀,也不添加任何标识信息,以指示它不是类。abstract class
interface
public interface Reader {}
public abstract class FileReader implements Reader {}
public class XmlFileReader extends FileReader {}
据说开发人员不需要知道上述类是或.abstract
interface
静态决赛
我个人的偏好和信念是,在提到变量时,我们应该遵循类似的逻辑。相反,我们在确定如何命名时会评估其用法。似乎全大写的论点是从C语言和C++语言中盲目采用的东西。在我看来,这并不是在Java中延续传统的理由。static final
意图问题
我们应该问问自己,在我们自己的语境中,它的功能是什么。以下是如何在不同上下文中使用的三个示例:static final
static final
public class ChatMessage {
//Used like a private variable
private static final Logger logger = LoggerFactory.getLogger(XmlFileReader.class);
//Used like an Enum
public class Error {
public static final int Success = 0;
public static final int TooLong = 1;
public static final int IllegalCharacters = 2;
}
//Used to define some static, constant, publicly visible property
public static final int MAX_SIZE = Integer.MAX_VALUE;
}
是否可以在所有三种情况下都使用全部大写?当然可以,但我认为可以说这会减损每个目的。因此,让我们单独检查每个案例。
用途:私有变量
在上面的示例中,记录器被声明为私有,并且只能在类中使用,或者可能是内部类。即使它是在 或 包
可见性 处声明的,它的用法也是相同的:Logger
protected
public void send(final String message) {
logger.info("Sending the following message: '" + message + "'.");
//Send the message
}
在这里,我们不关心这是一个成员变量。它可能只是一个实例变量。不知道。我们不需要知道。我们需要知道的是,我们正在将消息记录到类实例提供的记录器中。logger
static final
final
public class ChatMessage {
private final Logger logger = LoggerFactory.getLogger(getClass());
}
在这种情况下,您不会将其命名为,那么如果它是,为什么要将其全部命名为大写?在这两种情况下,其背景或意图是相同的。LOGGER
static final
注意:我改变了我对软件包
可见性的立场,因为它更像是一种公共
访问形式,仅限于软件包
级别。
用途:枚举
现在你可能会说,你为什么要用整数作为?这是一个仍在发展的讨论,我甚至会说是半有争议的,所以我会尽量不通过冒险来破坏这个讨论。但是,建议您实现以下可接受的枚举模式:static final
enum
public enum Error {
Success(0),
TooLong(1),
IllegalCharacters(2);
private final int value;
private Error(final int value) {
this.value = value;
}
public int value() {
return value;
}
public static Error fromValue(final int value) {
switch (value) {
case 0:
return Error.Success;
case 1:
return Error.TooLong;
case 2:
return Error.IllegalCharacters;
default:
throw new IllegalArgumentException("Unknown Error value.");
}
}
}
上述方法有一些变体,它们实现了允许显式转换 和 的相同目的。在通过网络流式传输此信息的范围内,本机 Java 序列化实在是太冗长了。一个简单的, ,或者可以节省巨大的带宽。我可以深入研究一个冗长的比较和对比,关于与涉及类型安全性,可读性,可维护性等的利弊;幸运的是,这超出了本次讨论的范围。enum->int
int->enum
int
short
byte
enum
static final int
底线是这样的,有时静态的最终int
将用作枚举
样式结构。
如果你能让自己接受上述说法是正确的,我们就可以继续讨论风格。在声明 时,接受的样式表示我们不执行以下操作:enum
public enum Error {
SUCCESS(0),
TOOLONG(1),
ILLEGALCHARACTERS(2);
}
相反,我们执行以下操作:
public enum Error {
Success(0),
TooLong(1),
IllegalCharacters(2);
}
如果你的整数块是松散的,那么你为什么要对它使用不同的命名约定呢?在这两种情况下,其背景或意图是相同的。static final
enum
用途:静态、常量、公共属性
这个用例可能是所有用例中最模糊和最有争议的。静态常量大小用法示例是最常遇到这种情况的地方。Java消除了对sizeof()的需求
,但有时知道数据结构将占用多少字节是很重要的。
例如,假设您正在向二进制文件写入或读取数据结构列表,并且该二进制文件的格式要求在实际数据之前插入数据块的总大小。这很常见,以便读者知道数据何时停止,因为接下来会有更多的不相关的数据。请考虑以下构成的文件格式:
File Format: MyFormat (MYFM) for example purposes only
[int filetype: MYFM]
[int version: 0] //0 - Version of MyFormat file format
[int dataSize: 325] //The data section occupies the next 325 bytes
[int checksumSize: 400] //The checksum section occupies 400 bytes after the data section (16 bytes each)
[byte[] data]
[byte[] checksum]
此文件包含序列化为字节流并写入此文件的对象列表。此文件有325个字节的对象,但是如果不知道每个对象的大小,就无法知道哪些字节属于每个。因此,您定义了 上的大小:MyObject
MyObject
MyObject
MyObject
MyObject
MyObject
public class MyObject {
private final long id; //It has a 64bit identifier (+8 bytes)
private final int value; //It has a 32bit integer value (+4 bytes)
private final boolean special; //Is it special? (+1 byte)
public static final int SIZE = 13; //8 + 4 + 1 = 13 bytes
}
数据结构在写入上述文件时将占用 13 个字节。知道了这一点,在读取我们的二进制文件时,我们可以动态地计算出文件中有多少个对象:MyObject
MyObject
int dataSize = buffer.getInt();
int totalObjects = dataSize / MyObject.SIZE;
这似乎是所有大写常量的典型用例和参数,我同意在这种情况下,所有大写都是有意义的。原因如下:static final
Java没有像C语言那样的类,但a只是一个包含所有公共成员而没有构造函数的类。它只是一个数据。因此,您可以以类似的方式声明一个:struct
struct
struct
class
struct
public class MyFile {
public static final int MYFM = 0x4D59464D; //'MYFM' another use of all uppercase!
//The struct
public static class MyFileHeader {
public int fileType = MYFM;
public int version = 0;
public int dataSize = 0;
public int checksumSize = 0;
}
}
让我在此示例的开头声明我个人不会以这种方式解析。我建议使用一个不可变的类,通过接受一个或所有4个变量作为构造函数参数来在内部处理分析。也就是说,访问(在本例中设置)此成员将如下所示:ByteBuffer
struct
MyFileHeader header = new MyFileHeader();
header.fileType = buffer.getInt();
header.version = buffer.getInt();
header.dataSize = buffer.getInt();
header.checksumSize = buffer.getInt();
这些不是 或 ,但它们是可以直接设置的公开公开成员。出于这个原因,我认为当一个成员公开时,将其完全大写是有意义的。这是将其与公共非静态变量区分开来的一次重要时刻。static
final
static final
注意:即使在这种情况下,如果开发人员尝试设置最终
变量,他们也会遇到 IDE 或编译器错误。
总结
总之,你为变量选择的约定将是你的偏好,但我坚信使用环境应该对你的设计决策产生重大影响。我个人的建议是遵循以下两种方法之一:static final
方法1:评估背景和意图[highly subjective; logical]
- 如果它是一个应该与实例变量无法区分的变量,则将它们命名为相同。全部小写
private
private
- 如果它的目的是用作值的松散样式块的类型,请将其命名为 .帕斯卡大小写:每个单词的首字母大写
enum
static
enum
- 如果它的目的是定义一些可公开访问的,常量和静态的属性,那么通过将其全部大写来使其突出
方法2:私人与公共[objective; logical]
方法论2基本上将其上下文浓缩为可见性,并且没有留下任何解释的余地。
- 如果是或那么它应该全部小写。
private
protected
- 如果是 或 那么 它应该全大写。
public
package
结论
这就是我如何看待变量的命名约定。我不认为这可以或应该被框定为一个单一的包罗万象的东西。我认为,在决定如何命名之前,您应该评估其意图。static final
但是,主要目标应该是尝试在整个项目/包的范围内保持一致。最后,这就是你所能控制的一切。
(我确实希望遇到阻力,但也希望从社区获得一些关于这种方法的支持。无论你的立场如何,在斥责、批评或赞扬这种风格选择时,请保持文明。