-1
struct S
{
    int arr[3];
    int x;
};


S s[3] = {{{1, 2, 3}, 111},
          {{2, 3, 4}, 222},
          {{3, 4, 5}, 333}};

The above code is C++

Is it possible to do something similar in Java? i.e. do a compile time initialization?

user93353
  • 13,733
  • 8
  • 60
  • 122

1 Answers1

3

Is it possible to do something similar in Java? i.e. do a compile time initialization?

No, not possible. Java allows compile-time constants solely for static final variables, with a primitive type or String type, initialized on the same line, and not with null. This can be 'recursive', and some basic math is allowed, as long as it all remains constant (see JLS §15.28).

Crucially then, integer arrays don't count.

But, the question one needs to ask is: why do you want it to be? Java isn't like C, and compile time constants don't buy you anything, except [A] if you have class file A that contains a constant, and you refer to it in B, and then compile B, and then A is not available at runtime, it won't matter. This is true, but, this rarely to never matters and is in fact somewhat annoying (if you later recompile A without recompiling B, B won't pick up teh change if it was a constant), and [B] it saves you some code that runs once per application execution.

B is also irrelevant - JVM bootup is orders of magnitude more expensive than a minimal C application's bootup; this JVM bootup completely dwarfs any concern here.

Thus, trivially, you think you want a compile time constant but you probably don't. If you really do, the answer is a simple: impossible.

If it's not so much about it being a compile time constant, but more about writing it in a succint manner, java has syntax sugar for 2D arrays, but does not have particularly fancy syntax to make structs and initialize them without naming them.

Note that in idiomatic java, the [] goes after the type and never after the variable. Yes, you can write it after the variable, but nobody does this - it's a holdover from 30 years ago when java syntax was explicitly designed to appeal to C coders.

Thus:

public record S(int[] arr, int x) {}

S[] s = {
  new S(new int[] {1, 2, 3}, 111),
  new S(new int[] {2, 3, 4}, 222),
  new S(new int[] {3, 4, 5}, 333)
};

is about as short as you can make it. You can omit the new S[] part only when writing an initializing expression for a variable declaration. S[] s is a variable declaration so we can skip it there, but the array values we're passing in aren't, thus, the new int[] part is not skippable. You could get fancy with constructors and do something like:

public record S(int[] arr, int x) {
    public S(int x, int... arr) {
        this(arr, x);
    }
}

// then you can go with:
S[] s = {
  new S(111, 1, 2, 3),
  new S(222, 2, 3, 4),
  new S(333, 3, 4, 5)
};

Golfing any further than this would take you then rather dark, extremely non-idiomatic and ill-advised java syntax hackery.

user207421
  • 305,947
  • 44
  • 307
  • 483
rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • Thank you - but `new S(new int[] {1, 2, 3}, 111}),` this seems to be missing an `{` – user93353 Jun 04 '21 at 03:11
  • ON the contrary, the final `}` should be deleted. – user207421 Jun 04 '21 at 03:27
  • Can you show how you have defined S in the 1st sample code - i am unable to get it to compile – user93353 Jun 04 '21 at 03:43
  • "Java syntax was explicitly designed to appeal to C coders" ... and C was explicitly designed to appeal to B coders, and ... It's really appalling how much bad syntax has come to us via that path, and how little via the best syntax designers of the 1960s: by whom I mean Wirth and Hoare. – user207421 Jun 04 '21 at 05:46
  • @user93353 The first code segment works for me, but it does require Java 16 or whenever records were introduced (I dozed off). – user207421 Jun 04 '21 at 07:22