An expression in a programming language is a combination of values, operators, variables and functions that are evaluated in a particular order of precedence to produce a value. An operator performs an operation on one or more operands to produce a value. In JavaFX Script, everything that is not a definition is an expression. This chapter describes the syntax, meaning, and the use of various expressions and operators in JavaFX Script.
Most of the operators in JavaFX Script are the same as in Java, with a very few exceptions. In this chapter, you will see the following operators in detail:
The assignment operator
Arithmetic operators
Unary operators
Relational operators
Logical operators
Operators combine multiple operands together to form an expression, and JavaFX Script supports different types of expressions. You will learn about the following expressions in this chapter:
Range expressions
Block expressions
Looping expressions
while
for
Conditional expressions
if-else
Error-handling expressions
try, catch, finally, throw
New expressions
The operators and expressions that are omitted from this chapter will be covered in subsequent chapters when we deal with the topics related to them. See the Summary of this chapter for more about expressions and operators not covered here.
Many of the examples that you have seen so far in previous chapters have used the assignment operator. Lets' take a close look at this operator. The assignment operator works just as in any other language—the value of the expression or the variable on the right side value is assigned to the variable on the left side. Listing 4-1 shows the syntax formats for an assignment operator.
Following is a simple example of a variable being initialized with a value while it is defined:
var width : Integer = 10;
This can be considered two statements merged into one—first a declaration statement and then the assignment statement. You can split it as follows:
var width : Integer; width =10;
Similarly, def variables are assigned with a constant definition when they are created, as shown next:
def PI = 3.142;
Here, PI
is a def
(constant definition) and holds a value, 3.142. Note that the data type of PI
is derived automatically from the value assigned to it through the assignment operator. In this case, it is of type Number.
Now let us see an expression with an assignment operator.
var area : Number = 3.142 * r * r;
In this example, the arithmetic expression on the right side is evaluated first and then assigned to the variable on the left.
Assignments are not restricted to evaluating a simple expression and assigning its result to the variable on the left; they can also be used for creating an instance of a class, as shown in the following example.
var button : Button = Button { text : "Click Me" }
Here, an instance of a Button class
(JavaFX class) is created and assigned to a variable named button
. In the next example, an instance of a java.io.File
class is created and assigned to a variable named File
.
var file : java.io.File = new File("HelloWorld.java");
You will learn more about class definitions and objects in Chapter 6,"Class Definitions."
In Listing 4-2, different datatype values are assigned to different variables and are printed on the console using the println
output statement.
Example 4.2. A simple program using the assignment operator
var a : Integer = 10; var b : Boolean = true; var pi : Number = 22.0/7.0; var dur : Duration = 10ms; var name : String = "JavaFX is cool..! "; println("a = {a}"); println("b = {b}"); println("pi = {pi}"); println("dur ={ dur}"); println("name = {name}");
Output
a = 10 b = true pi = 3.142 dur =10ms name = JavaFX is cool..!
Sometimes you may need to assign the same value to multiple variables. Instead of using multiple assignment statements, you can do that in a single assignment statement, as follows:
a = b = c;
The value of c
is first assigned to b
, and then the b
value to a
.
The as
operator is used to convert one data type to another. In JavaFX Script ,as
is a keyword and is used to do type casting. You learned about type casting in Chapter 3, "Data Types," so the following is just a refresher. Listing 4-3 shows a simple example of how as
can be used.
In Listing 4-3, the value of the variable PI
has been assigned to an Integer variable, x
. Since PI
is of type Number and we are narrowing its precision to Integer, the compiler will show a warning that there is a loss of precision if you don't use the as
operator. Using as
, indicates to the compiler that the programmer knows what he or she is doing and hence the compiler need not worry. So in this example, the compiler does not display any warning.
Casting is not just limited to numeric data types but can be extended to user-defined data types as well. You will learn more about this in Chapter 6, "Class Definitions" and Chapter 8, "Inheritance," when we deal with the concept of superclasses and subclasses.
The arithmetic operators are binary operators and are used in arithmetic expressions. The arithmetic operators can be combined with the assignment operator to perform arithmetic and assignment operations both together. The usage of these operators is pretty much the same as in any other language.
Table 4-1 shows the arithmetic operators with their precedence; the Example column demonstrates how they can be used.
Table 4.1. Operator Precedence for Arithmetic Operators
Operator | Meaning | Precedence | Example |
---|---|---|---|
| Multiplication | 1 |
|
| Division | 2 |
|
| Modulus | 3 |
|
| Addition | 4 |
|
| Subtraction | 5 |
|
In JavaFX Script the modulus or remainder operator is represented by the keyword mod
. The mod operator returns the remainder of a division operation. It can be applied to the Number and Integer data types. Listing 4-4 demonstrates the use of the modulus operator, and the code is self-explanatory.
Example 4.4. Using the modulus operator
var numMod = 22.0 mod 7.0; println("numMod = {numMod}"); var intMod = 22 mod 7; println("intMod = {intMod}");
Output
numMod = 1.0 intMod = 1
In Java, the mod operator is represented by the '% symbol.
When an arithmetic operator is combined with an assignment operator, it is called an arithmetic assignment operator. This operator allows you to do the arithmetic and assignment operation in a single statement. The arithmetic assignment operators have the following syntax:
variable = variable arithmetic operator expression;
Using an arithmetic assignment operator is best suited for cases when a variable is used in an expression and the same variable is used to store the result of the expression. Here is a simple example:
x = x + 2;
The variable x
is used in an arithmetic operation, and the same variable is used to store the value of the expression as well. So we are using the variable x
twice. Using an arithmetic assignment operator, the same expression can be simplified as follows:
x+=2;
Both statements perform the same operation; that is, they increment the value of the variable x
by 2. Similarly, other arithmetic operators can also be combined with the assignment operator to perform the respective arithmetic and assignment operations in a single statement.
Each operator is assigned a precedence or priority, which determines the order in which the operator operates on the operand. As in an ordinary arithmetic expression, multiplication and division have a higher precedence than addition and subtraction. If two operators have the same precedence, they are executed according to the order in which they appear in the statement. For most operators (except the assignment operator), the order is from left to right.
Let's look at an example to see how an expression is evaluated and in what order:
x = 20 + 50.0 * 7 / 2;
Since the multiplication (*) and division (/) operators have the highest precedence, they are executed first, followed by the addition (+) operation.
50.0 * 7 // since both * and / operators have the same precedence and multiplication(*) is on the left side, multiplication is done first, yielding the result 350.0. 350.0 / 2 // the next highest precedence is the / operator, so division is done next, yielding the result 175.0. 20 + 175.0 // the final operator left in the expression is addition (+), which yields the value 195.0, which is the final value of the expression that is assigned to 'x'
If you want to change the order of the execution, enclose the respective operator and the operands in parentheses. Let us rewrite the previous example as follows:
x =(20 + 50.0) * 7 / 2;
Now the operation (20 + 50.0) is evaluated first, since the parentheses take precedence over multiplication. You can see the operator precedence across all the JavaFX Script operators in Table 4.4, at the end of the "Operators" section.
A single operator operating on a single value is called a unary operator. The following unary operators are available in JavaFX Script:
Increment and Decrement
Unary − and +
Unary not
The increment (++) and decrement (−−) operators perform a simple task. The first increments (increases) the value of its operand by 1 and the second decrements (decreases) the value of its operand by 1. There are two variants of each of these operators: prefix mode and postfix mode. Listing 4-5 shows the prefix and suffix syntax for unary increment operators and Listing 4-6 shows the prefix and suffix syntax for unary decrement operators.
Example 4.5. Syntax of the unary increment operator
++variable
; // prefix form of Increment operatorvariable
++; // postfix form of Increment operator
Example 4.6. Syntax of the unary decrement operator
--variable
; // prefix form of decrement operatorvariable
-- // postfix form of decrement operator
In prefix mode the operator comes before the affected variable, and in postfix mode it comes after the variable. As demonstrated in the examples in Listing 4-7, the two modes differ in the timing at which the incrementing/ decrementing takes place.
Example 4.7. Unary increment/decrement operators
1. var x : Integer = 10; 2. var y = x++; 3. var z = ++x; 4. println("x = {x} y = {y} z = {z}"); // x = 12 y = 10 z = 12 5. var p = x--; 6. var q = --x; 7. println("x = {x} p = {p} q = {q}"); // x = 10 p = 12 q = 10
Output
x = 12 y = 10 z = 12 x = 10 p = 12 q = 10
In line 1, we declare a variable x
and initialize its value to 10. In line 2, we are incrementing x
using the postfix ++
operator and at the same time assigning the value of this expression to y
. Looking at the line, you may assume that the value of y
will be 11. But that is not correct because the value of the expression before the increment is assigned to y
and x
value is incremented afterward. Hence y
will take the value of 10 and after this assignment; x
will be incremented to 11.
Similarly, in line 3, we are assigning ++x
to a variable z
. Here x
will be incremented first and then assigned to z
. Hence, x
increments from 11 to 12, and this value is assigned to z
. This is the exact difference between prefix and postfix mode. In postfix mode, the expression is evaluated first and incremented or decremented after, whereas in postfix mode, the value is incremented/decremented first and then the expression is evaluated. Now you can apply the same logic to variables p
and q
as well.
Listing 4-8 provides another example of how prefix and postfix modes differ from each other.
Example 4.8. Prefix and postfix operators
1. var x : Integer = 7; 2. println("initial value x = {x}"); 3 println("postfix variant incrementng the value of x = {x++}"); 4. println("value x = {x}"); 5. println("prefix variant incrementng the value of x = {++x}"); 6. println("value x = {x}");
initial value x = 7 postfix variant incrementng the value of x = 7 value x = 8 prefix variant incrementng the value of x = 9 value x = 9
If you understood the example in Listing 4-7, you can easily predict the results for Listing 4-8 without looking at the output.
In line 1, we are declaring a variable x
and initializing it with 7. In line 2, we are printing the value of x
, which is 7. In line 3, we are incrementing x
with the postfix increment operator and printing its value. Since postfix incrementing happens after the evaluation of the expression in which it is involved, println()
is executed first, printing the actual value of x
, which is 7.
After the print
operation, the value of x
is incremented to 8. In line 4, we print the incremented value of x
, which is 8. In line 5, we are again printing the x
value and at the same time incrementing it using the prefix increment operator. Here the incrementing happens before the print()
operation, so println()
prints the incremented value of x
, which is 9.
The same evaluation logic applies to the prefix and postfix decrement operator as well.
Hence, the choice between using prefix and postfix operators depends on the context—the actual expression in which the operator is involved and the expected value of the respective expression.
JavaFX Script variables can hold either positive numbers (by default all number are positive) or negative numbers. If you need to specify a number as negative, then you need to put a minus (−) sign in front of the value or the variable. The minus sign can be used to change the algebraic sign of a value or a variable:
var c = −10 ;
This example states that −10 is assigned to a variable c
. In the same way, the value of an expression can be made negative by applying the minus sign in front of the expression, as in the following example:
var d = - ( x * x );
Here, the variable d
will hold the negative value of the square of x
.
As mentioned at the beginning of this section, there is also a unary + operator. Its use is implicit, since all numbers are positive by default.
The not operator is a unary operator used to complement either a relational or a logical expression. Listing 4-9 shows its syntax.
The not
operator negates the value of the logical or relational expression that follows it. If the expression evaluates to True, the not
operator will change that to False and vice-versa. Listing 4-10 shows an example.
Example 4.10. Using the not operator
var a = 10; var b = 5; var x : Boolean = not ( a > b ); println(x);
Output
false
As you see in the example, the actual value of the relational expression is true
since a
is greater than b
. But the not operator changes that to false
while assigning it to variable x
.
In Java, the negation operator is represented by ! (the exclamation symbol).
Relational operators are used to compare the relationship between two operands. Relational expressions involving these operators always produce Boolean results and are often used in conditional expressions, as you will see later in this chapter. Table 4-2 shows the relational operators available in JavaFX Script.
All relational operators except equal (==) and not equal (!=) can be applied only to simple data types like Integer or Number. Equal to and Not Equal To can be applied to objects as well.
var x = 10 > 5;
Here we are comparing whether 10 is greater than 5. Since 10 is greater than 5, the value of x
after executing the statement will be True. Since relational expressions fetch a Boolean result, the data type of x
would automatically be inferred as Boolean by the compiler.
Logical operators are binary operators used to combine the value of two or more relational expressions. Similar to relational expressions, logical expressions also produce only Boolean results.
Table 4-3 shows the logical operators available in JavaFX Script.
Table 4.3. Logical Operators
Operator | Meaning | Syntax |
---|---|---|
| Logical AND operator |
|
| Logical OR operator |
|
Logical operators work as cutoff or short-circuit operators. For example, if an and operator combines two relational expressions to form a logical expression, and the relational expression on the left side evaluates to False, then the value of the whole logical expression evaluates to False and the right- side relational expression is not evaluated at all. In the same way, if an or logical operator combines two relational expressions and the left- side relational expression evaluates to True, then the right expression is ignored and the value of the whole logical expression becomes True.
Here is an example of how two relational expressions are combined with a logical operator:
var x = ( 10 > 5 and 2 < 5 ); var firstGrade = ( totalMark => 60 or totalMarks <= 80 );
Besides using variables or data values as you've seen, the relational expressions combined by the logical operators can also include complex expressions as well.
In Java, the logical operators are represented by different symbols - && for AND and || for OR. In JavaFX Script, they have been deliberately named in plain English for convenience.
Table 4-4 summarizes the operator precedence for all the operators available in JavaFX Script.
Table 4.4. Operator Precedence in JavaFX Script
Operator | Description | Precedence |
---|---|---|
| Parentheses | 1 |
| Post increment | 2 |
-- | Post decrement | |
| Post increment | 3 |
-- | Post decrement | |
| Logical complement | |
| Size of a sequence | |
| Index of a sequence element | |
| Reversing a sequence order | |
| Tween operator | Continued |
| Multiplication | 4 |
| Division | |
| modulus | |
| Addition | 5 |
| Subtraction | |
| Equal | 6 |
| Not equal | |
| Less than | |
| Less than or equeal to | |
| Greater than | |
| Greater than or equal to | |
| Type checking | 7 |
| Cast | |
| Logical AND | 8 |
| Logical OR | 9 |
| Addition and assignment | 10 |
| substraction and assignment | |
| multiplication and assignment | |
| Division and assignment | |
| Modulus and assignment | |
| Assignment | 11 |
A range expression defines a sequence of numeric values forming an arithmetic series, using the syntax shown in Listing 4-11.
A range expression defines a sequence whose elements consist of the integers from number1
to number2
inclusive. The following example shows a simple range expression.
var nums = [0..3]; println (nums);
Output
[ 0, 1, 2, 3 ]
A range expression must have a starting and an ending value and may optionally specify a step value, to define the number by which the sequence must be incremented. The default step value of 1 is used if none is specified. The following example would redefine the previous range with a step value of 2.
var nums = [0..3 step 2]; println (nums);
Output
[ 0, 2]
Here, the resulting sequence just includes 0, 2 and not the final value. When there is a step value, first the starting value is included in the sequence and then the step factor is applied repeatedly until the end value is reached. Note that the end value 3 is not included here since it does not meet the step
criteria.
The range expression can be pictorially represented as shown in Figure 4-1.
In this diagram, the three valueExpression
s must be of either type Integer or Number. If any of them is of type Number, the rangeExpression
will become a sequence of Numbers.
Table 4-5 shows examples of range expressions with corresponding output values.
Table 4.5. Range Expressions
Range Expression | Value | Comments |
---|---|---|
| [1, 2, 3, 4, 5] | Uses the default step value of 1. |
| [1, 2, 3, 4] | All values between 1 and 5, inclusive of 1 but exclusive of 5. |
| [1.0, 2.0, 3.0, 4.0, 5.0] | A number sequence of values between 1.0 and 5.0. |
| [3.6, 4.6, 5.6, 6.6] | 3.6, then 3.6 + 1, and so on until the end value is reached. |
| [1, 3, 5, 7, 9] | All values between 1 and 9 with an explicit step of 2 |
| [100, 97, 94, 91] | Negative step. Values decrease. |
| [0.0, 0.25, 0.5, 0.75, 1] | Fractional step value. |
| [0.0, 0.25, 0.5, 0.75] | Fractional step value, excluding the end value in the range. |
| [] | Compiler Warning: "empty sequence range literal, probably not what you meant." For descending sequences, step value must be negative. |
| [ 4, 5, 6, 7, 8, 9, 10 ] | Expressions as start/end values. |
| [ 4, 6, 8, 10 ] | Start/End/Step values as expressions. |
| [] | Compiler Warning: "Empty sequence range literal, probably not what you meant." For ascending sequences, step value must be positive. |
Range expressions are unique to JavaFX in the sense that they are not available in Java. Range expressions have varied applications in JavaFX Script in places such as sequences, for loops, and so on. Because range expressions can be defined by using other expressions to define their start, end, and step values, these expressions can become very powerful and can greatly simplify the way for loops and sequences are defined.
A block is a collection of definitions and/or expressions surrounded by curly braces and separated by semicolons. The value of the block expression is the value of the last expression in the block. If the last statement is not an expression, then the value of the block is Void
. Listing 4-12 shows an example.
Example 4.12. Example of a block expression
println( { var sum = 0; var counter = 10; while (counter > 0) { sum += counter; --counter; } "Sum is {sum}" } );
Output
Sum is 55
As you can see, the value of the block enclosed within the println()
is the value of the last expression, which is Sum is {sum}
.
Listing 4-13 illustrates a conditional block expression.
Example 4.13. Example of a conditional block expression
var flag: Boolean = true; var x = if (flag) { 45 * 2 + 10; } else { 90 * 2 + 20; } println(x);
Output
100 (if flag value is true as given in the code) 200 (if flag value is changed to false)
Here, the value of the if
and else
blocks takes the value of the arithmetic expression defined within the block since that is the last (only) expression in the block. Please note that the variables declared within a block can be used only in that block or in its child blocks, since they are local to the block.
Using the type and value of the last expression as the type/value of the block comes handy in many places. One good example is in functions where you don't have to have a return expression explicitly at the end of the block, and the last expression's value would be returned automatically. Similarly, the function need not explicitly declare a return type; the return type would be inferred automatically from the last expression of the function block. You will learn more about this in Chapter 5, "Functions."
Loops are an integral part of any programming language; they are used to control the flow of execution. Looping expressions are iterative; they repeat until the Boolean expression that controls the loop evaluates to False. JavaFX Script offers two types of looping constructs: for
and while
. You will examine each of them in detail in this section.
The for
expression iterates over one or more sequences. The value of the for
expression comes from its body. If the body is of type Void
, the value of the for expression would also be Void
. The body of the forloop
is executed for each valid value specified by the range (which you specify within square brackets [ ]).
The Void type indicates that an expression does not have a value. Examples of Void expressions are the while expression and calls to functions that have no return value. The only time Void can be used to declare a type explicitly is to declare the return type of a function that does not return a value. You will see this in detail in Chapter 5. For now, Void can be considered to be equivalent of an expression having "no value."
Listing 4-14 is a simple example of a for
expression.
In this example, the syntax [x..y]
is a range expression representing a range of values. Here the loop repeats for five times, with i
taking values from 1 to 5 (inclusive). No need to declare the variable i
explicitly outside the for
loop, as it will be implicitly created when the loop begins and discarded when the loop is terminated. The value of the for
-expression is considered to be Void
since the body of the for
-expression (println
) does not have a valid return value.
Listing 4-15 demonstrates a for
expression that returns a valid value.
Example 4.15. Example of a for expression with a valid value
var seq = for (i in [1..3]) 2 * i; println(seq);
Output
[2, 4, 6]
Here, i
takes the value of 1 to 3, and the body of the for
-expression returns a valid value of i
multiplied by 2. Since the for
-expression yields a valid value, it can be assigned to a variable of type Sequence. Though we have not explicitly defined seq
to be of type Sequence, the compiler will infer the type automatically to be Integer[ ], since the for
expression returns multiple values. Hence the code shown in Listing 4-15 would yield the same result as this:
var seq: Integer [] = [2, 4, 6];
A for expression is always expected to return a sequence, even if it just returns a single value. The compiler will always try to infer the data type as a sequence when the result of the for expression is assigned to a variable.
The for
expression can be pictorially represented as shown in Figure 4-2.
As you can see, a for
expression can have multiple in
clauses; an in
clause can be defined pictorially as shown in Figure 4-3.
An in
clause typically returns a range of values for which the loop has to repeat, and both a for
-Expression and an in
clause can optionally include a where
clause to validate the values from the given range conditionally.
The for
examples that you have seen so far have used a single in
-clause within the for
-expression.
Now let us see a for
expression with multiple in
clauses.
var seq = for (x in [1..2], word in ["Richard", "Brian"]) "{x} {word}";
Having multiple in
clauses can be considered like having a nested for
-loop in Java. When we have more than one in
clause, the rightmost in
clause acts as the innermost loop.
The output of the previous example is as follows:
seq = [ 1 Richard, 1 Brian, 2 Richard, 2 Brian ]
The same code can be replicated in a conventional way as shown in Listing 4-16.
Example 4.16. Example of a conventional for expression with multiple in clauses
var seq: String[]; for (x in [1..2]) { for (word in ["Richard", "Brian"]) { insert "{x} {word}" into seq; } } println(seq);
Output
[ 1 Richard, 1 Brian, 2 Richard, 2 Brian ]
As you see, this code has yielded the same result as that of the for
expression with multiple in
clauses shown previously. Here the insert
statement just inserts a new element into the sequence; you will learn more about this in Chapter 10, "Sequences."
So far, we have only seen plain in
clauses that do not validate the range values conditionally. In Listing 4-17, you can see how to validate the range values conditionally within an in
clause using where
.
Example 4.17. Example of a for expression with conditional validation
var words = for (length in [3..6], word in ['moose', 'wolf', 'turkey', 'bee'] where word.length() >= length) word;
In this example, the inner in
clause validates if a specific range value size actually exceeds the length (specified by the outer in
clause), and this range value would be used only if the condition is met.
Now let's see iteratively how the sequence is built when the value of length
changes from 3 to 6:
Iteration 1
length = 3 seq = ['moose', 'wolf', 'turkey', 'bee']
Iteration 2
length = 4 seq = ['moose', 'wolf', 'turkey', 'bee', 'moose', 'wolf', 'turkey']
Iteration 3
length = 5 seq = ['moose', 'wolf', 'turkey', 'bee', 'moose', 'wolf', 'turkey', 'moose', 'turkey']
Iteration 4
length = 6 seq = ['moose', 'wolf', 'turkey', 'bee', 'moose', 'wolf', 'turkey', 'moose', 'turkey', 'turkey']
As you see in the output, in the second iteration bee
is dropped from the range of word
since the condition defined by the where
clause is not satisfied. Similarly wolf
is dropped for iteration 3 and moose
is dropped for iteration 4.
The same example can also be written in the conventional way as shown in Listing 4-18.
Example 4.18. Example of the conventional way of using conditional validations in a for expression
var words = for (length in [3..6]) { for (word in ['moose', 'wolf', 'turkey', 'bee']) { if (word.length() >= length) { word } else { null } } };
The output of Listing 4-18 is the same as that of Listing 4-17.
The else
part in Listing 4-18 generates a null
value but unlike in Java, null
values are ignored and not inserted into the sequence.
The range expressions in a for
loop can themselves contain expressions and can also depend on the range value of the previous in
clause, such as the one shown in Listing 4-19.
Example 4.19. Example of an expression within a range expression
var seq = for (x in [1..5], y in [1..(x-1)]) { println("X Val: {x}, Y Val: {y}, Mod Val: {x mod y}"); x mod y; } println(seq);
Output
X Val: 2, Y Val: 1, Mod Val: 0 X Val: 3, Y Val: 1, Mod Val: 0 X Val: 3, Y Val: 2, Mod Val: 1 X Val: 4, Y Val: 1, Mod Val: 0 X Val: 4, Y Val: 2, Mod Val: 0 X Val: 4, Y Val: 3, Mod Val: 1 X Val: 5, Y Val: 1, Mod Val: 0 X Val: 5, Y Val: 2, Mod Val: 1 X Val: 5, Y Val: 3, Mod Val: 2 X Val: 5, Y Val: 4, Mod Val: 1 [ 0, 0, 1, 0, 0, 1, 0, 1, 2, 1 ]
In this example note that the first iteration of x
value, with a value of 1, is skipped because it does not fetch a valid y
value. The rest of the output is self-explanatory.
With the combination of range expression, multiple in
clauses, and conditional validation of the range values, the for
expression in JavaFX Script makes looping code much simpler, less verbose, and very powerful.
While
expressions are the same in JavaFX Script as in Java. The expression specified after the close parenthesis repeats as long as the Boolean expression controlling the while
loop evaluates to True. Listing 4-20 shows a simple example of a while
loop, and the code is self-explanatory.
A while expression can be pictorially represented as shown in Figure 4-4.
In Figure 4-4, valueExpression
yields a binary value (True or False), based on which the execution of the while loop is repeated. Unlike a for
expression, the value of the while
expression is always Void
and hence it cannot be used in assignments like for
expressions.
A break
expression is used to terminate (abruptly) a loop in which it is lexically contained and needs to be used with while
or for
expressions. The value of the break
expression is always Void
since it abruptly ends the execution of a loop. Usage of break
in JavaFX Script is same as in Java. Listing 4-21 shows an example.
This example uses a break
expression to break the while
loop conditionally.
Now let us see how to use this from within a for
expression, as shown in Listing 4-22.
Example 4.22. Example of using break within a for expression
var words: String[]; for (length in [3..6]) { for (word in ['moose', 'wolf', 'turkey', 'bee']) { if (word.length() >= length) { insert word into words; } else { break; } } };
Output
words = [ moose, wolf, turkey, bee, moose, wolf, turkey, moose ]
The code in Listing 4-22 breaks the inner loop whenever the length of word
does not meet the length specified by the outer loop.
The continue
expression is the same in JavaScript as in Java. It abruptly completes the current iteration of the loop in which it is lexically contained and attempts to start the next iteration. The statements that follow continue
won't be executed and control is transferred to the top of the loop. Listing 4-23 demonstrates a continue
expression.
Example 4.23. Example of a continue expression
var notPrime = false; for (x in [2..100]) { for (y in [2..(x-1)]) { if (x mod y == 0) { notPrime = true; break; } } if (notPrime) { notPrime = false; continue; } else { print("{x} "); } }
Output
2 3 5 7 11S 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
This example is self-explanatory. However, note that the value of continue
is also always Void
.
The if-else
expression in JavaFX Script is pretty much the same as in Java. If-else
is probably the most basic way of controlling program flow. The if-else
expression in JavaFX Script uses the truth or falsehood of the associated conditional expression to decide the program flow. If the conditional expression evaluates to True, the first block of code or the expression following the conditional expression is executed. If the conditional expression evaluates to false, the else block is executed.
The if-else expression can be pictorially represented as shown in Figure 4-5.
As described in Figure 4-5, the else and then parts of the if-else expression are optional.
The value of an if
expression can either be a valid value or Void
depending on the value that the first and second expressions evaluate to. If the else part is present and if neither of the expressions are of the Void
type, then the if
expression will have a valid value. The value will be that of the first expression if valueExpression
evaluates to True and will be that of the second if valueExpression
is False. If the valueExpression
is False and if there is no else block, the value of the if
expression would be Void
.
The Java language has the if-else statement as well as the ternary operator, such as a > b? a: b. In JavaFX Script, the same if statement is used for both, thanks to block expressions. You will find both usages in the examples given in this chapter.
Listing 4-24 shows a simple if-else
expression.
Example 4.24. Example of an if-else expression
var mark: Integer = 60; if (mark >= 50) { println("PASS"); } else { println ("FAIL"); }
Output
PASS
The same expression can alternatively be specified in one statement, as shown in the following example. Here we omit the braces since there is only one statement in each of the blocks.
If (mark >= 50) println("PASS") else println("FAIL");
Since the value of mark
is 60, this will print PASS
. If the mark
value is changed to anything less than 50, then the else
block will be executed, printing FAIL
. The value of the if
expression as such would be Void
since neither of the expressions have a valid value here.
Since the if-else expression can bear a value, it can be used to assign a value to a variable conditionally, as shown in Listing 4-25.
Example 4.25. Example of if-else with a value
var flag = true; var x = if (flag) "JavaFX" else 3.14; println(x);
Output
JavaFX
This result occurs because flag
is set to True. If the ) flag
value is changed to false, the output would be 3.14.
In Listing 4-25, the type of the variable x
would be an Object here as there is no more specific type that has String and Number as sub-types.
When using if-else
expressions for assignments, you have to ensure there is an else
part and both the expressions given under if
and else
yield valid values. If not, this would result in a compilation error.
Neither Java nor JavaFX Script allows you to use a number as a Boolean the way C and C++ do, where truth is non-zero and falsehood is zero. So, If you need to use a number a, you should first change it to Boolean through a conditional expression such as (a != 0) or (a > 0).
Exception handling in JavaFX Script is almost the same as in Java. The same try-catch-finally
blocks used in Java are applicable to JavaFX Script as well but need to be written with JavaFX Script variable declaration syntax.
Listing 4-26 shows a simple example of how the try-catch-finally
is written in JavaFX Script.
Example 4.26. Example of a try-catch-finally block
try { throw new Exception("Demonstrating try-catch-finally"); } catch (e:Exception) { println("Exception thrown {e}"); } finally { println("finally reached"); }
Listing 4-26 could also be written as follows:
try { throw new Exception("Demonstrating try-catch-finally"); } catch (any) { println("Exception thrown {any}"); } finally { println("finally reached"); }
Output
Exception thrown java.lang.Exception: Demonstrating try-catch-finally finally reached
Listing 4-26 throws an exception intentionally from within the try
block to see if it is caught by the respective catch
block. As you see in the output, the respective catch
block as well as the finally
block are called when the exception is thrown. Now let us see in detail how this works in JavaFX Script.
The typical try-catch-finally
and throw
clauses in JavaFX Script are pictorially described in Figures 4-6 through 4-8. First, Figure 4-6 shows the complete try-catch-finally
structure.
The try
block (Figure 4-6) is executed until either an exception is thrown or it finishes successfully. When there is an exception, each catch
clause is inspected to see which of the catch
block's formalParameter
s matches that of the exception thrown. Figure 4-7 represents the catch
block pictorially.
If any of the catch blocks is tuned to receive the exception thrown, the respective block is executed, with formalParameter
replaced with the exception object. No further catch
blocks will be executed. If none of the catch
blocks match the exception thrown, then the exception propagates out of the try-catch-finally
blocks.
A finally
block, if present, will always be executed after the try
block regardless of whether any exception is thrown.
The throw
expression in JavaFX Script (Figure 4-8) is same as in Java and causes an exception to be thrown. Since it completes abruptly, it does not have any value.
A try
expression does not have any value and hence it is of type Void
.
A new
expression is used to create instance of a Java class. It allows us to specify the parameters required by the constructor of the respective Java class. Figure 4-9 is a diagram of its syntax, and listing 4-27 shows some examples of the new
operator to create instances of Java classes.
Example 4.27. Examples of the new expression
var f = new java.io.File("JavaFX.txt"); var fis: java.io.FileInputStream = new java.io.FileInputStream("Sun.doc"); var str = new java.lang.String("JavaFX is cool");
Instances of JavaFX classes can also be created with the new
operator, but it is recommended to use object literals for JavaFX class instances. You will see more about object literals when we deal with class definitions in JavaFX Script.
In JavaFX Script, one expression must be differentiated from another by a semicolon, without which there will be a compilation error. Listing 4-28 shows good and bad examples.
Example 4.28. Correctly and incorrectly differentiating expressions
println(n) // This line would show a compilation error for missing semicolon var xx = 9; // Correct var yy = 100 // This will not show a compilation error since there are no expressions following this one.
Output
You have forgotten the ';', which is needed to separate one expression from the next. println(n) ^
Hence it is important to close an expression with a semicolon (;) when there are further expressions following it.
JavaFX Script operators operate on one or more operands or values and produce either a Boolean or Numeric value or a reference. Arithmetic, Relational and logical operators are binary operators. The mod, increment/decrement, not, −, and + are unary operators. Each operator is assigned a precedence or priority which determines the order in which the operator operates on the operand.
Some operators are not covered in this chapter; they are as follows:
indexof
instanceof
sizeof
reverse
In this chapter, you have also learned about various expressions such as for
, while
, break
, continue
, if-else
, range
, block
, try-catch-finally
, and so on, its syntax and usage. There are still more expressions that are not covered here, such as
Object literals
Qualified names
PostFix expressions
Member access
Function invocation
This
Sequence
Selection
Indexing
Slice
Function expressions
Timeline expressions
The operators and expressions not covered in this chapter will be covered in later chapters when we go in-depth into topics such as class definitions, access modifiers, functions, timelines, and so on. In the next chapter, you will learn more about functions in JavaFX Script and their usage.