Print
Typing

MVEL is dynamically typed language, with static typing. Most users of MVEL will rely simply on dynamic typing. It's simple, and easy to work with.

a = 10; // declare a variable 'a'
b = 15; // declare a variable 'b';

a + b;
The var Keyword

Although like JavaScript and Ruby, MVEL has reserved the var keyword for variable declaration, it is not implemented in version 1.2. While it may be eventually implemented in the upcoming 2.0 release, please note that it is currently not optional to prefix declarations with this keyword. As such, since it reserved in the parser, it is also not possible to use the name var as an identifier.

Dynamic Typing and Coercion

The most important aspect of a language like MVEL, which interacts directly with native Java objects, which themselves are statically typed, is that of type coercion. Since MVEL cannot truly treat say, a java.lang.String object as a java.lang.Integer object for math operations, it must be able to coerce one type to another.

Performance Considerations

This is of course a serious performance consideration when using something like MVEL as an integration point at a hot spot of your application. For heavy processing load, coercion overload is mitigated by caches and the MVEL optimizers (available only for pre-compiled expressions). However it is not always possible to bypass the overhead of a hard coercion operation depending on what is being done.

However, if String variables are being injected into the runtime to be evaluated as Integers, it is simply not possible to prevent the runtime from needing to parse the strings into new Integer objects. This should always be considered.

Method Calls

Calling of methods is one of the most important aspects of coercion. Fundamentally, it allows you to directly call method without the need to finesse the inputs. Instead the interpreter or compiler will analyze the types being passed to the method, determine what coercion needs to be done to accomplish the call, and in the case of overloaded methods, choose the method which most closely matches the input types by avoiding using coercion if possible.

Arrays

Arrays are one of the more interesting aspects of the coercion system in MVEL, in that, MVEL uses untyped arrays by default (meaning Object[] arrays for all intents and purposes). Only when faced with a array type conflict, will MVEL attempt to coerce the entire array to the needed input type. For example: in the case of a method call parameter.

Example:

myArray = {1,2,3};

// pass to method that accepts String[]
myObject.someMethod(myArray);

In this particular case, someMethod() accepts a String[] array. This will not fail in MVEL, instead MVEL will convert the array to a String[].

Static Typing

Static typing in MVEL functions just as it does in Java, but by default still works in concert with coercion.

int num = 10;

This declares a typed integer variable called num. When you do this, the MVEL runtime will enforce the type. For example, trying to assign an incompatible type after the declaration will result in an exception:

num = new HashMap(); // will throw an incompatible typing exception.

However, MVEL will perform coercion to a statically typed variable if the value being assigned is coercable.

num = "100"; // will work -- parses String to an integer.
Only once in scope

Once you have declared a statically typed variable, you cannot declare a new variable of the same name within the scope. For example:

int i = 100;

int i = 200; // will throw an exception.

Strict Typing

Strict typing in MVEL is an optional mode for the compiler, in which all types must be fully qualified, either by declaration or inference.

Enabling Strict Mode

When compiling an expression, the compiler can be put into strict mode through the ParserContext by setting setStrictTypeEnforcement(true).

Satisfying type strictness can be accomplished both by requiring explicit declaration of types inside the expression, or by notifying the parser ahead of time of what the types of certain inputs are.

For example:

ExpressionCompiler compiler = new ExpressionCompiler(expr);

ParserContext context = new ParserContext();
context.setStrictTypeEnforcement(true);

context.addInput("message", Message.class);
context.addInput("person", Person.class);

compiler.compile(context);

In this example we inform the compiler that this expression will be accepting two external inputs: message and person and what the types of those inputs are. This allows the compiler to determine if a particular call is safe at compile time, instead of failing at runtime.

Powered by Atlassian Confluence