0

OK, so there's something that bothers me a little in the Java syntax that I don't quite understand.

When an annotation accepts an array as one of its argument's value, we can do so by providing the values inside a couple of brackets, like so:

public @interface SomeAnnotation {
  String[] someParam();
}
@SomeAnnotation(someParam = { "foo", "bar" })
public class Example {}

This is a very neat and concise way of passing an array of values. Love it.

But the same can not be done when calling a method:

public interface Example {
  public static void someMethod(String[] someParam) {
    // Do something
  }
}

// ...
Example.someMethod({ "foo", "bar" }); // Syntax Error :(

From the look of it, both the annotation's someParam and the method someParam are declared as a String[] array.

I suppose its related to the way annotation are handled by Java under the hood, and/or the fact that someParam is declared like a kind of method (with parenthesis at the end) in SomeAnnotation, but still... why?

If someone out there could shed some light on this, I would be very grateful.

Please note that I'm not looking for alternatives or workaround, but rather some explanations.

Subsequent question

I know I could call the method with the new String[]... syntax, like so:

Example.someMethod(new String[] { "foo", "bar" });

But that also seems strange to me since the param is supposed to be an array of String and the values inside the brackets are indeed Strings. I would expect the compiler to be able to match things up and be OK with that.

Tazaf
  • 350
  • 5
  • 15

1 Answers1

2

The simple explanation is that this is the way that the Java language was specified. Designing the syntax for a new programming language is a compromise between expressiveness and conciseness versus simplicity / readability and non-ambiguity.

The basic Java syntax is what they arrived at in ~1995. From then onward, the Java designers have been constrained by the implicit requirement that any changes to the language syntax must not "break" older code1.

Annotations are actually a case in point. The @ <Identifier> syntactic marker creates a new context where new rules will not interfere with older parts of the Java syntax. This allowed them to use a simpler / cleaner way of writing "array literals" in the new context. So they did. But they couldn't do the same thing more generally2 without creating parsing problems and/or breaking old Java code.


1 - Or that any breakages should be minimal. For example, changing enum to a keyword in Java 5 broke a tiny proportion of existing Java code that used "enum" as identifier. This caused a bit of angst. So when they introduced var in Java 10, they made it "reserved type name" rather than a full keyword.
2 - At at least, I assume that they couldn't. If they could have done it, I think that they would have done it in the past 25 years or so. Most people agree that Java array initialization is a bit clunky.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Thanks for those explanations. The part about having to deal with legacy syntax VS being free to simplify it on new features is really convincing. – Tazaf Mar 17 '21 at 15:02