-1

Is the purpose of abstract keyword in a FunctionalInterface to distinguish the 'lambda' method from other abstract methods?

Since methods that have no body in an interface are abstract, and Functional Interfaces that have only one method do not have the abstract keyword, I was wondering whether the real purpose of the abstract keyword is to mark or distinguish which among the 'abstract' methods in a Functional Interface will serve as the 'carrier' of the lambda expression. Is my understanding correct?

This method does not have the abstract keyword but is a functional interface:

public interface AllTrades {
  public boolean checkSalary(ATrade t);
}

now suppose the interface above had 2 methods, they are both abstract, but the interface is no longer a FunctionalInterface

public interface AllTrades {
  public boolean checkSalary(ATrade t);
  public boolean checkSalary2(ATrade t);
}

Now if we mark which method is abstract, it is a Functional Interface again:

public interface AllTrades {
  abstract public boolean checkSalary(ATrade t);
  public boolean checkSalary2(ATrade t);
}

Is my understanding correct?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
likejudo
  • 3,396
  • 6
  • 52
  • 107
  • 1
    did you _try_ to compile the second? – Eugene Sep 30 '21 at 16:16
  • 2
    @Eugene The second will compile, but won't be a functional interface, but as the OP didn't annotate it with `@FunctionalInterface`, the compile will not fail at this point (though attempting to assign a lambda or method reference to a variable of this type will fail to compile). – Mark Rotteveel Sep 30 '21 at 16:27
  • 1
    @MarkRotteveel exactly my point. if OP _tried_ anything related to the question, the answer would have been obvious. – Eugene Sep 30 '21 at 16:33
  • 1
    @Eugene you are mistaken in your assumptions. Yes, both will compile. Notice I did not use the FunctionalInterface annotation in my examples. – likejudo Sep 30 '21 at 16:43
  • 1
    As for your suggestion, Groovy allows for it [when implementing an interface with a Closure](https://docs.groovy-lang.org/latest/html/documentation/core-semantics.html#_closure_to_arbitrary_type_coercion), however there is no way to do that in Java. Java's static typing makes it impossible with current Lambda Expressions, since each of the abstract methods in an Interface may have a different return type, yet a Lambda Expression has a single return type based on the expression it returns. – qwerty Sep 30 '21 at 17:34
  • @qwerty it was a suggestion for the language to be modified in future. in my 3rd example, checkSalary() would carry the lambda when invoked with such an expression. – likejudo Sep 30 '21 at 17:47
  • `checkSalary2` would need to be implemented, though. Otherwise, it defeats the purpose of using an interface. How would that issue be resolved in this hypothetical modification? Groovy can allow it because it has dynamic typing, so the same Closure can be used (at compile time) for any method. – qwerty Sep 30 '21 at 18:03

2 Answers2

3

Although you can use abstract in an interface, it has no extra meaning, as all methods in an interface (except default, private or static methods) are by definition abstract. It has no extra meaning in a functional interface, and if you annotate your interface with @FunctionalInterface, both of your examples with two methods will fail to compile as they are equivalent.

To be complete, your first example does have an abstract method, and is a potential function interface. Your second and third example both have two abstract methods, and cannot be used as a function interface.

See also the Java Language Specification 17, section 9.4:

An interface method lacking a private, default, or static modifier is implicitly abstract. Its body is represented by a semicolon, not a block. It is permitted, but discouraged as a matter of style, to redundantly specify the abstract modifier for such a method declaration.

(emphasis mine)

and section 9.8:

A functional interface is an interface that is not declared sealed and has just one abstract method (aside from the methods of Object), and thus represents a single function contract.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • Can I use the third example as a Functional Interface without annotating it as such - since I have marked the single abstract method? That was the point of my question but unfortunately, someone has voted to close it. – likejudo Sep 30 '21 at 16:31
  • 1
    @likejudo No you cannot, because it has two abstract methods, and a functional interface must have one and only one abstract method. Your compiler will also tell you this if you add the `@FunctionalInterface` annotation to your interface. – Mark Rotteveel Sep 30 '21 at 16:32
  • that is good to know that both methods are abstract even though one was marked as abstract. it will be useful to others to reopen the question. – likejudo Sep 30 '21 at 16:35
  • 1
    @likejudo I think I understand what's confusing you. All methods in interfaces are abstract by default, [unless an implementation is provided](https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html) (in which case the default modifier must be used.) The `abstract` keyword is intended to be used only in [abstract classes](https://docs.oracle.com/javase/specs/jls/se17/html/jls-8.html#jls-8.1.1.1), where methods are not abstract by default. – qwerty Sep 30 '21 at 16:38
  • @MarkRotteveel I edited my question with a suggestion – likejudo Sep 30 '21 at 17:25
  • 1
    @likejudo I have rolled back your edit as it fundamentally alters your question and makes it opinion-based. – Mark Rotteveel Oct 01 '21 at 07:41
2

All methods in interfaces are public and abstract by default, and the inclusion of either of those modifiers does not change the behavior of the code in any way. You can verify this by compiling the second and third code samples with the @FunctionalInterface annotation, which would result in a compile time error.

Edit: From the Java Language Specification

9.8. Functional Interfaces

9.4.3. Interface Method Body

9.6.4.9. @FunctionalInterface

qwerty
  • 810
  • 1
  • 9
  • 26