[[painless-variables]] === Variables A variable loads and stores a value for evaluation during <>. [[variable-declaration]] ==== Declaration Declare a variable before use with the format of <> followed by <>. Declare an <> variable using an opening `[` token and a closing `]` token for each dimension directly after the identifier. Specify a comma-separated list of identifiers following the type to declare multiple variables in a single statement. Use an <> combined with a declaration to immediately assign a value to a variable. A variable not immediately assigned a value will have a default value assigned implicitly based on the type. *Errors* * If a variable is used prior to or without declaration. *Grammar* [source,ANTLR4] ---- declaration : type ID assignment? (',' ID assignment?)*; type: ID ('.' ID)* ('[' ']')*; assignment: '=' expression; ---- *Examples* * Different variations of variable declaration. + [source,Painless] ---- <1> int x; <2> List y; <3> int x, y = 5, z; <4> def d; <5> int i = 10; <6> float[] f; <7> Map[][] m; ---- + <1> declare `int x`; store default `null` to `x` <2> declare `List y`; store default `null` to `y` <3> declare `int x`; store default `int 0` to `x`; declare `int y`; store `int 5` to `y`; declare `int z`; store default `int 0` to `z`; <4> declare `def d`; store default `null` to `d` <5> declare `int i`; store `int 10` to `i` <6> declare `float[] f`; store default `null` to `f` <7> declare `Map[][] m`; store default `null` to `m` [[variable-assignment]] ==== Assignment Use the `assignment operator '='` to store a value in a variable for use in subsequent operations. Any operation that produces a value can be assigned to any variable as long as the <> are the same or the resultant type can be <> to the variable type. *Errors* * If the type of value is unable to match the type of variable. *Grammar* [source,ANTLR4] ---- assignment: ID '=' expression ---- *Examples* * Variable assignment with an integer literal. + [source,Painless] ---- <1> int i; <2> i = 10; ---- + <1> declare `int i`; store default `int 0` to `i` <2> store `int 10` to `i` + * Declaration combined with immediate assignment. + [source,Painless] ---- <1> int i = 10; <2> double j = 2.0; ---- + <1> declare `int i`; store `int 10` to `i` <2> declare `double j`; store `double 2.0` to `j` + * Assignment of one variable to another using primitive type values. + [source,Painless] ---- <1> int i = 10; <2> int j = i; ---- + <1> declare `int i`; store `int 10` to `i` <2> declare `int j`; load from `i` -> `int 10`; store `int 10` to `j` + * Assignment with reference types using the <>. + [source,Painless] ---- <1> ArrayList l = new ArrayList(); <2> Map m = new HashMap(); ---- + <1> declare `ArrayList l`; allocate `ArrayList` instance -> `ArrayList reference`; store `ArrayList reference` to `l` <2> declare `Map m`; allocate `HashMap` instance -> `HashMap reference`; implicit cast `HashMap reference` to `Map reference` -> `Map reference`; store `Map reference` to `m` + * Assignment of one variable to another using reference type values. + [source,Painless] ---- <1> List l = new ArrayList(); <2> List k = l; <3> List m; <4> m = k; ---- + <1> declare `List l`; allocate `ArrayList` instance -> `ArrayList reference`; implicit cast `ArrayList reference` to `List reference` -> `List reference`; store `List reference` to `l` <2> declare `List k`; load from `l` -> `List reference`; store `List reference` to `k`; (note `l` and `k` refer to the same instance known as a shallow-copy) <3> declare `List m`; store default `null` to `m` <4> load from `k` -> `List reference`; store `List reference` to `m`; (note `l`, `k`, and `m` refer to the same instance) + * Assignment with array type variables using the <>. + [source,Painless] ---- <1> int[] ia1; <2> ia1 = new int[2]; <3> ia1[0] = 1; <4> int[] ib1 = ia1; <5> int[][] ic2 = new int[2][5]; <6> ic2[1][3] = 2; <7> ic2[0] = ia1; ---- + <1> declare `int[] ia1`; store default `null` to `ia1` <2> allocate `1-d int array` instance with `length [2]` -> `1-d int array reference`; store `1-d int array reference` to `ia1` <3> load from `ia1` -> `1-d int array reference`; store `int 1` to `index [0]` of `1-d int array reference` <4> declare `int[] ib1`; load from `ia1` -> `1-d int array reference`; store `1-d int array reference` to `ib1`; (note `ia1` and `ib1` refer to the same instance known as a shallow copy) <5> declare `int[][] ic2`; allocate `2-d int array` instance with `length [2, 5]` -> `2-d int array reference`; store `2-d int array reference` to `ic2` <6> load from `ic2` -> `2-d int array reference`; store `int 2` to `index [1, 3]` of `2-d int array reference` <7> load from `ia1` -> `1-d int array reference`; load from `ic2` -> `2-d int array reference`; store `1-d int array reference` to `index [0]` of `2-d int array reference`; (note `ia1`, `ib1`, and `index [0]` of `ia2` refer to the same instance)