10

I know about the Oracle Java naming conventions and I've read similar SO questions (like Java constant variable, naming convention) but what naming should I use for constant functions?

E.g. if I have the functional interface

public interface StringDecider {
  public boolean decide(String str);
}

and now I'm using it to define a constant function. Should the naming be 'upper snake case', like

public final static StringDecider STRING_NOT_EMPTY = (str) -> (str!=null && !str.isEmpty());
STRING_NOT_EMPTY.decide("Example");

or camel case

public final static StringDecider stringNotEmpty = (str) -> (str!=null && !str.isEmpty());
stringNotEmpty.decide("Example");
15
  • 3
    @sotirios-delimanolis I disagree that this duplicates the linked question. OP knows that historically static final variables are capitalised. They are asking whether to make an exception for functions. I think it "feels" right to do so. Was looking for precedent, when the question was closed. Commented Nov 7, 2016 at 17:19
  • 2
    I suggest you change your question to use the Java 8 function types. i.e. final static Predicate<String> STRING_NOT_EMPTY versus final static Predicate<String> stringNotEmpty. This underlines that it's a question inspired by Java 8's addition of lambdas. Commented Nov 7, 2016 at 17:28
  • 1
    Anyhow, short version of the answer that I would have posted: your IDE will probably advise you to use SNAKE_CASE_CAPS like any other static final variable. I failed to find any examples in the JDK source. I found some examples in Guava that use SNAKE_CASE_CAPS. I myself feel that a local convention in which you do different would be OK, because myStream.map(MY_FUNCTION) feels ugly. I feel static final functions should be sort-of peers to methods, and capitalised accordingly. But that's just me. Commented Nov 7, 2016 at 17:43
  • 3
    Of course, it feels weird to write STRING_NOT_EMPTY.decide("Example"), but that’s because it makes no sense to create a function object via lambda expression, just to call directly a method on it. The natural way is to write a method static boolean isNotEmpty(String str) { … } and call isNotEmpty("Example"). Then, if you need a function object, e.g. of type StringDecider just use ContainingType::isNotEmpty. No sane programmer would call String.CASE_INSENSITIVE_ORDER .compare(s1, s2); the natural way is using an ordinary method, i.e. s1.compareToIgnoreCase(s2) Commented Nov 7, 2016 at 17:58
  • 2
    I don't think ALL_CAPS_THING.method(foo); feels weird to write at all. Not if you've used enums in earnest. Or pre-compiled regex patterns. Commented Nov 8, 2016 at 10:19

3 Answers 3

4

In Java, there is no such thing as a "constant function": A lambda constructs an object which has a single method, and, like all other objects, it can be assigned to a reference — including a final reference. At the level of your reference StringDecider STRING_NOT_EMPTY, there is no distinction between an object which has been created using a lambda and one created through any other means. Therefore, the term "constant" doesn't have a different meaning depending on what constructs were used to define and construct the constant object.

In fact, beyond their definition in code, there is no discernible difference between a lambda function object and e.g. an anonymous class object:

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();
    }

};

For all intents and purposes, STRING_NOT_EMPTY_LAMBDA and STRING_NOT_EMPTY_ANON have an equivalent function — they were simply defined using different syntax, which may or may not be implemented differently.

Conclusion

At the level of referencing, there is no distinction of whether an object was defined using a lambda or not. Therefore, for constants created using a lambda, you probably should use the same conventions you use for constants created in other ways for consistency's sake:

public final static int ANSWER_TO_LIFE_THE_UNIVERSE_AND_EVERYTHING = 42;

public final static StringDecider STRING_NOT_EMPTY = str -> (str != null && !str.isEmpty());

If, for whatever reason, you and/or your team want to discern between the two, feel free to do so... but make sure to stay consistent.


In fact, lambdas and anonymous classes need not be implemented in the same way. However, their usage is identical once they are created (there are few differences such as in variable scope, but, once the object is created and assigned to StringDecider STRING_NOT_EMPTY, these differences are no longer relevant).

Sign up to request clarification or add additional context in comments.

Comments

1

When something is constant, you use uppercase letters with underscores to separate the words. That's the same for everything, variables, fields, objects and constant lambdas too.

from Oracle's site:

The names of variables declared class constants and of ANSI constants should be all uppercase with words separated by underscores ("_"). (ANSI constants should be avoided, for ease of debugging.)

10 Comments

Define constant.
@SotiriosDelimanolis Based on a dictionary: Constant a situation/object that does not change.
Don't base it on a dictionary definition. Base it on a language specification. What does the Java language consider a constant? How does it apply to this example?
I guess he means static final fields by the term constant in Java context. Though it's true that constant per se is not semantically defined in Java terms. I'd say something being constant has more to do with being final and immutable.
@Bálint They do, but in the JLS it's used in a more restricted sense in terms such as "constant expression", which is an entirely different beast. Hence why it's important that you explicitly define what you mean by it: there is no single definition in Java for the word "constant". If you for example define it as "any field marked as final", I'd disagree that they should all be captialised.
|
0

Your IDE will probably warn you if you fail to use SNAKE_CASE_CAPS like any other static final variable.

Nothing I could find from Oracle suggests that you should treat a lambda differently from any other type, in this respect.

I failed to find any examples in the JDK source. I found some examples in Guava that use SNAKE_CASE_CAPS.


However teams and individuals can and do invent local conventions (for example, some projects use snake_case_lower_case_for_test_methods_in_jUnit()), and if you feel it's useful, you could adopt a local convention in your case.

I personally feel that:

  • myStream.map(MY_FUNCTION) feels a bit ugly.
  • declaring lambdas at the top of the file, among the other variables, feels a bit ugly.

I feel static final functions should be "sort-of peers" to methods, capitalised and placed accordingly, so it feels more natural to me to have something like:

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;

... than to declare the function at the top of the file as FOO_TO_STRING. We usually write private methods below the public methods that use them. It seems reasonable to me to write private functions below the public methods that use them, too.

But note, there's a lot of "feels" in my justification here, which may or may not be enough reason.


I note that in the Oracle Java source, the standard code sidesteps this issue, by not using static variables when it could. For example, in Function.java:

 static <T> Function<T, T> identity() {
      return t -> t;
 }

... returns an inline new Function object, rather than reusing a shared Function object stored in a class or object variable.


Note also that you can declare ordinary static methods and use them as functions, with the slight overhead of using this or the class name with :::

private static String slimify(String s) {
    return "Slim says: " + s;
}

...

out = stream.map(this::slimify).collect(Collectors.toList());

(I don't currently get a compiler warning about using this in a static context)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.