270 lines
10 KiB
Plaintext
270 lines
10 KiB
Plaintext
[[painless-types]]
|
|
=== Types
|
|
|
|
Painless supports both dynamic and static types. Static types are split into
|
|
_primitive types_ and _reference types_.
|
|
|
|
[[dynamic-types]]
|
|
==== Dynamic Types
|
|
|
|
Painless supports one dynamic type: `def`. The `def` type can represent any
|
|
primitive or reference type. When you use the `def` type, it mimics the exact
|
|
behavior of whatever type it represents at runtime. The default value for the
|
|
def type is `null.`
|
|
|
|
Internally, if the `def` type represents a primitive type, it is converted to the
|
|
corresponding reference type. It still behaves like the primitive type, however,
|
|
including within the casting model. The `def` type can be assigned to different
|
|
types during the course of script execution.
|
|
|
|
IMPORTANT: Because a `def` type variable can be assigned to different types
|
|
during execution, type conversion errors that occur when using the `def` type
|
|
happen at runtime.
|
|
|
|
Using the `def` type can have a slight impact on performance. If performance is
|
|
critical, it's better to declare static types.
|
|
|
|
*Examples:*
|
|
[source,Java]
|
|
----
|
|
def x = 1; // Declare def variable x and set it to the
|
|
// literal int 1
|
|
def l = new ArrayList(); // Declare def variable l and set it a newly
|
|
// allocated ArrayList
|
|
----
|
|
|
|
[[primitive-types]]
|
|
==== Primitive Types
|
|
|
|
Primitive types are allocated directly onto the stack according to the standard
|
|
Java memory model.
|
|
|
|
Primitive types can behave as their corresponding (<<boxing-unboxing, boxed>>)
|
|
reference type. This means any piece of a reference type can be accessed or
|
|
called through the primitive type. Operations performed in this manner convert
|
|
the primitive type to its corresponding reference type at runtime and perform
|
|
the field access or method call without needing to perform any other
|
|
operations.
|
|
|
|
Painless supports the following primitive types.
|
|
|
|
byte::
|
|
An 8-bit, signed, two's complement integer.
|
|
Range: [-128, 127].
|
|
Default value: 0.
|
|
Reference type: Byte.
|
|
|
|
short::
|
|
A 16-bit, signed, two's complement integer.
|
|
Range: [-32768, 32767].
|
|
Default value: 0.
|
|
Reference type: Short.
|
|
|
|
char::
|
|
A 16-bit Unicode character.
|
|
Range: [0, 65535].
|
|
Default value: 0 or `\u0000`.
|
|
Reference type: Character.
|
|
|
|
int::
|
|
A 32-bit, signed, two's complement integer.
|
|
Range: [-2^32, 2^32-1].
|
|
Default value: 0.
|
|
Reference type: Integer.
|
|
|
|
long::
|
|
A 64-bit, signed, two's complement integer.
|
|
Range: [-2^64, 2^64-1].
|
|
Default value: 0.
|
|
Reference type: Long.
|
|
|
|
float::
|
|
A 32-bit, single-precision, IEEE 754 floating point number.
|
|
Range: Depends on multiple factors.
|
|
Default value: 0.0.
|
|
Reference type: Float.
|
|
|
|
double::
|
|
A 64-bit, double-precision, IEEE 754 floating point number.
|
|
Range: Depends on multiple factors.
|
|
Default value: 0.0.
|
|
Reference type: Double.
|
|
|
|
boolean::
|
|
A logical quanity with two possible values: true and false.
|
|
Range: true/false.
|
|
Default value: false.
|
|
Reference type: Boolean.
|
|
|
|
|
|
*Examples:*
|
|
[source,Java]
|
|
----
|
|
int i = 1; // Declare variable i as an int and set it to the
|
|
// literal 1
|
|
double d; // Declare variable d as a double and set it to the
|
|
// default value of 0.0
|
|
boolean b = true; // Declare variable b as a boolean and set it to true
|
|
----
|
|
|
|
Using methods from the corresponding reference type on a primitive type.
|
|
|
|
[source,Java]
|
|
----
|
|
int i = 1; // Declare variable i as an int and set it to the
|
|
// literal 1
|
|
i.toString(); // Invokes the Integer method toString on variable i
|
|
----
|
|
|
|
[[reference-types]]
|
|
==== Reference Types
|
|
|
|
Reference types are similar to Java classes and can contain multiple pieces
|
|
known as _members_. However, reference types do not support access modifiers.
|
|
You allocate reference type instances on the heap using the `new` operator.
|
|
|
|
Reference types can have both static and non-static members:
|
|
|
|
* Static members are shared by all instances of the same reference type and
|
|
can be accessed without allocating an instance of the reference type. For
|
|
example `Integer.MAX_VALUE`.
|
|
* Non-static members are specific to an instance of the reference type
|
|
and can only be accessed through the allocated instance.
|
|
|
|
The default value for a reference type is `null`, indicating that no memory has
|
|
been allocated for it. When you assign `null` to a reference type, its previous
|
|
value is discarded and garbage collected in accordance with the Java memory
|
|
model as long as there are no other references to that value.
|
|
|
|
A reference type can contain:
|
|
|
|
* Zero to many primitive types. Primitive type members can be static or
|
|
non-static and read-only or read-write.
|
|
* Zero to many reference types. Reference type members can be static or
|
|
non-static and read-only or read-write.
|
|
* Methods that call an internal function to return a value and/or manipulate
|
|
the primitive or reference type members. Method members can be static or
|
|
non-static.
|
|
* Constructors that call an internal function to return a newly-allocated
|
|
reference type instance. Constructors are non-static methods that can
|
|
optionally manipulate the primitive and reference type members.
|
|
|
|
Reference types support a Java-style inheritance model. Consider types A and B.
|
|
Type A is considered to be a parent of B, and B a child of A, if B inherits
|
|
(is able to access as its own) all of A's fields and methods. Type B is
|
|
considered a descendant of A if there exists a recursive parent-child
|
|
relationship from B to A with none to many types in between. In this case, B
|
|
inherits all of A's fields and methods along with all of the fields and
|
|
methods of the types in between. Type B is also considered to be a type A
|
|
in both relationships.
|
|
|
|
For the complete list of Painless reference types and their supported methods,
|
|
see the https://www.elastic.co/guide/en/elasticsearch/reference/current/painless-api-reference.html[Painless API Reference].
|
|
|
|
For more information about working with reference types, see
|
|
<<field-access, Accessing Fields>> and <<method-access, Calling Methods>>.
|
|
|
|
*Examples:*
|
|
[source,Java]
|
|
----
|
|
ArrayList al = new ArrayList(); // Declare variable al as an ArrayList and
|
|
// set it to a newly allocated ArrayList
|
|
List l = new ArrayList(); // Declare variable l as a List and set
|
|
// it to a newly allocated ArrayList, which is
|
|
// allowed because ArrayList inherits from List
|
|
Map m; // Declare variable m as a Map and set it
|
|
// to the default value of null
|
|
----
|
|
|
|
Directly accessing static pieces of a reference type.
|
|
|
|
[source,Java]
|
|
----
|
|
Integer.MAX_VALUE // a static field access
|
|
Long.parseLong("123L") // a static function call
|
|
----
|
|
|
|
[[string-type]]
|
|
==== String Type
|
|
|
|
A `String` is a specialized reference type that is immutable and does not have
|
|
to be explicitly allocated. You can directly assign to a `String` without first
|
|
allocating it with the `new` keyword. (Strings can be allocated with the `new`
|
|
keyword, but it's not required.)
|
|
|
|
When assigning a value to a `String`, you must enclose the text in single or
|
|
double quotes. Strings are allocated according to the standard Java Memory Model.
|
|
The default value for a `String` is `null.`
|
|
|
|
*Examples:*
|
|
[source,Java]
|
|
----
|
|
String r = "some text"; // Declare String r and set it to the
|
|
// String "some text"
|
|
String s = 'some text'; // Declare String s and set it to the
|
|
// String 'some text'
|
|
String t = new String("some text"); // Declare String t and set it to the
|
|
// String "some text"
|
|
String u; // Declare String u and set it to the
|
|
// default value null
|
|
----
|
|
|
|
[[void-type]]
|
|
==== void Type
|
|
|
|
The `void` type represents the concept of no type. In Painless, `void` declares
|
|
that a function has no return value.
|
|
|
|
[[array-type]]
|
|
==== Array Type
|
|
|
|
Arrays contain a series of elements of the same type that can be allocated
|
|
simultaneously. Painless supports both single and multi-dimensional arrays for
|
|
all types except void (including `def`).
|
|
|
|
You declare an array by specifying a type followed by a series of empty brackets,
|
|
where each set of brackets represents a dimension. Declared arrays have a default
|
|
value of `null` and are themselves a reference type.
|
|
|
|
To allocate an array, you use the `new` keyword followed by the type and a
|
|
set of brackets for each dimension. You can explicitly define the size of each dimension by specifying an expression within the brackets, or initialize each
|
|
dimension with the desired number of values. The allocated size of each
|
|
dimension is its permanent size.
|
|
|
|
To initialize an array, specify the values you want to initialize
|
|
each dimension with as a comma-separated list of expressions enclosed in braces.
|
|
For example, `new int[] {1, 2, 3}` creates a one-dimensional `int` array with a
|
|
size of 3 and the values 1, 2, and 3.
|
|
|
|
When you initialize an array, the order of the expressions is maintained. Each expression used as part of the initialization is converted to the
|
|
array's type. An error occurs if the types do not match.
|
|
|
|
*Grammar:*
|
|
[source,ANTLR4]
|
|
----
|
|
declare_array: TYPE ('[' ']')+;
|
|
|
|
array_initialization: 'new' TYPE '[' ']' '{' expression (',' expression) '}'
|
|
| 'new' TYPE '[' ']' '{' '}';
|
|
----
|
|
|
|
*Examples:*
|
|
[source,Java]
|
|
----
|
|
int[] x = new int[5]; // Declare int array x and assign it a newly
|
|
// allocated int array with a size of 5
|
|
def[][] y = new def[5][5]; // Declare the 2-dimensional def array y and
|
|
// assign it a newly allocated 2-dimensional
|
|
// array where both dimensions have a size of 5
|
|
int[] x = new int[] {1, 2, 3}; // Declare int array x and set it to an int
|
|
// array with values 1, 2, 3 and a size of 3
|
|
int i = 1;
|
|
long l = 2L;
|
|
float f = 3.0F;
|
|
double d = 4.0;
|
|
String s = "5";
|
|
def[] da = new def[] {i, l, f*d, s}; // Declare def array da and set it to
|
|
// a def array with a size of 4 and the
|
|
// values i, l, f*d, and s
|
|
----
|