我知道Oracle Java的命名约定,我读过类似的SO问题(如Java常量变量,命名约定),但我应该为常量函数使用什么命名?
。如果我有功能界面
public interface StringDecider {
public boolean decide(String str);
}
现在我用它来定义一个常数函数。是否应该命名为"大写蛇形字母",如
public final static StringDecider STRING_NOT_EMPTY = (str) -> (str!=null && !str.isEmpty());
STRING_NOT_EMPTY.decide("Example");
或驼峰式
public final static StringDecider stringNotEmpty = (str) -> (str!=null && !str.isEmpty());
stringNotEmpty.decide("Example");
在Java中,没有"常量函数"这样的东西:lambda构造一个具有单一方法的对象,并且,像所有其他对象一样,它可以被分配给引用—包括一个final
参考。在引用StringDecider STRING_NOT_EMPTY
的级别上,使用lambda创建的对象和通过任何其他方式创建的对象之间没有区别。因此,术语"常量"的含义并不取决于用来定义和构造常量对象的构造。
事实上,除了它们在代码中的定义之外,lambda函数对象和匿名类对象之间没有明显的区别†:
public final static StringDecider STRING_NOT_EMPTY_LAMBDA = str -> (str != null && !str.isEmpty());
public final static StringDecider STRING_NOT_EMPTY_ANON = new StringDecider() {
@Override
public boolean decide(final String str) {
return str != null && !str.isEmpty();
}
};
无论如何,STRING_NOT_EMPTY_LAMBDA
和STRING_NOT_EMPTY_ANON
具有等效的函数—它们只是使用不同的语法来定义,可能会或可能不会以不同的方式实现。结论
在引用级别,对象是否使用lambda定义没有区别。因此,对于使用lambda创建的常量,为了一致性起见,您可能应该使用与以其他方式创建常量相同的约定:
public final static int ANSWER_TO_LIFE_THE_UNIVERSE_AND_EVERYTHING = 42;
public final static StringDecider STRING_NOT_EMPTY = str -> (str != null && !str.isEmpty());
如果,无论出于何种原因,您和/或您的团队想要区分这两者,请随意这样做……但一定要保持一致。
†事实上,lambdas和匿名类不需要以相同的方式实现。然而,一旦它们被创建,它们的用法是相同的(有一些差异,比如在变量范围内,但是,一旦对象被创建并分配给StringDecider STRING_NOT_EMPTY
,这些差异就不再相关了)。
当某些内容是常量时,可以使用带下划线的大写字母来分隔单词。这对所有东西都是一样的,变量,字段,对象和常量。
from Oracle's site:
声明类常量和ANSI常量的变量名应该全部大写,单词之间用下划线(_)分隔。(为了便于调试,应该避免使用ANSI常量。)
如果您没有像使用其他静态final变量那样使用SNAKE_CASE_CAPS
, IDE可能会警告您。
在这方面,我从Oracle中找不到任何建议您应该将lambda与其他类型区别对待。
我没有在JDK源代码中找到任何示例。我在Guava中发现了一些使用SNAKE_CASE_CAPS
的例子。
然而,团队和个人可以并且确实发明了本地约定(例如,一些项目使用snake_case_lower_case_for_test_methods_in_jUnit()
),如果您觉得它有用,您可以在您的情况下采用本地约定。
我个人觉得:
-
myStream.map(MY_FUNCTION)
感觉有点丑 - 在文件的顶部声明lambdas,在其他变量中,感觉有点难看。
我觉得静态final函数应该与方法"类似",大写并相应地放置,所以对我来说更自然的是:
private List<String> asStrings(List<Foo> foos) {
return foos.stream().map(fooToString).collect(toList());
}
private static final Function<Foo,String> fooToString = f ->
"Foo: " + foo.id;
…不如在文件的顶部将函数声明为FOO_TO_STRING
。我们通常将私有方法写在使用它们的公共方法的下面。在我看来,把私有函数写在使用它们的公共方法下面也是合理的。
但请注意,我在这里的理由中有很多"感觉",这可能是也可能不是足够的理由。
我注意到,在Oracle Java源代码中,标准代码通过尽可能不使用静态变量来回避这个问题。例如,在Function.java
中:
static <T> Function<T, T> identity() {
return t -> t;
}
…返回一个内联的新Function
对象,而不是重用存储在类或对象变量中的共享Function
对象。
还请注意,您可以声明普通的静态方法并将它们用作函数,使用this
或::
的类名的轻微开销:
private static String slimify(String s) {
return "Slim says: " + s;
}
...
out = stream.map(this::slimify).collect(Collectors.toList());
(我目前没有得到关于在静态上下文中使用this
的编译器警告)