Java Class Interaction

Introduced: 7.0

Java Class Interaction

Lucee provides seamless integration with Java classes, allowing you to instantiate objects, call methods, and access static members directly from CFML code. This powerful feature enables you to leverage the entire Java ecosystem within your Lucee applications.

Overview

Java class interaction in Lucee supports multiple approaches for working with Java objects:

  • Implicit class loading using standard Java syntax
  • Explicit class loading with the java: prefix
  • Import statements for cleaner code
  • Static method calls and field access
  • Inner and nested class instantiation
  • Class reflection capabilities

Note: This feature was partially available as an experimental feature in Lucee 6.2, but should not be used in production systems with that version. The complete, stable implementation is available starting with Lucee 7.0.

Basic Class Instantiation

Implicit Loading

The most straightforward way to create Java objects is using implicit loading with the new keyword:

// Create a HashMap instance
map = new java.util.HashMap();
dump(map);

// Create an ArrayList with initial capacity list = new java.util.ArrayList(10); dump(list);
// Create a Date object currentDate = new java.util.Date(); dump(currentDate);

Explicit Loading

For better clarity and to avoid potential conflicts, you can use explicit loading with the java: prefix:

// Create a HashMap explicitly
map = new java:java.util.HashMap();
dump(map);

// Create a StringBuilder with initial value sb = new java:java.lang.StringBuilder("Hello World"); dump(sb);
// Create a BigDecimal for precise calculations decimal = new java:java.math.BigDecimal("123.456"); dump(decimal);

Import Statements

Use import statements to simplify class names and make your code more readable:

// Import specific classes
import java.util.HashMap;
import java.util.ArrayList;
import java.lang.StringBuilder;

// Now you can use simplified names map = new HashMap(); list = new ArrayList(); sb = new StringBuilder("Test");
dump(map); dump(list); dump(sb);
// Import entire packages with wildcard import java.util.*; import java.text.*;
// Use any class from imported packages map = new HashMap(); list = new LinkedList(); format = new SimpleDateFormat("yyyy-MM-dd");
dump(map); dump(list); dump(format);

Static Method Calls

Access static methods using the double colon (::) operator:

Implicit Static Calls

// Call Math.random()
rnd = Math::random();
dump(rnd);

// Call System.currentTimeMillis() timestamp = System::currentTimeMillis(); dump(timestamp);
// Call Integer.parseInt() number = Integer::parseInt("42"); dump(number);
// Call Arrays.toString() import java.util.Arrays; arr = [1, 2, 3, 4, 5]; str = Arrays::toString(arr); dump(str);

Explicit Static Calls

// Call static methods explicitly
rnd = java:Math::random();
dump(rnd);

// Call System properties osName = java:System::getProperty("os.name"); dump(osName);
// Call UUID generation import java.util.UUID; uuid = java:UUID::randomUUID(); dump(uuid);

Static Field Access

Access static fields (constants) using the same syntax:

// Access Integer constants
maxInt = java:Integer::MAX_VALUE;
minInt = java:Integer::MIN_VALUE;
dump(maxInt);
dump(minInt);

// Access Calendar constants import java.util.Calendar; monday = Calendar::MONDAY; sunday = Calendar::SUNDAY; dump(monday); dump(sunday);
// Access File separator separator = java:java.io.File::separator; dump(separator);

Inner and Nested Classes

Lucee supports instantiation of inner and nested classes using the $ delimiter:

Static Nested Classes

// Create a Map.Entry using AbstractMap.SimpleEntry
entry = new java:java.util.AbstractMap$SimpleEntry("count", 42);
dump(entry);

// Access the key and value dump("Key: " & entry.getKey()); dump("Value: " & entry.getValue());
// Create a Rectangle2D.Double rectangle = new java:java.awt.geom.Rectangle2D$Double(10.0, 20.0, 100.0, 50.0); dump(rectangle); dump("Area: " & (rectangle.getWidth() * rectangle.getHeight()));

Enum Classes

// Access Thread.State enum values
state = java:Thread$State::RUNNABLE;
dump(state & ""); // Convert to string for display

// Get all enum values states = java:Thread$State::values(); dump(states);
// Access other enum types import java.util.concurrent.TimeUnit; seconds = TimeUnit::SECONDS; minutes = TimeUnit::MINUTES; dump(seconds); dump(minutes);

Character Inner Classes

// Access Character.UnicodeBlock
basicLatin = java:Character$UnicodeBlock::BASIC_LATIN;
dump(basicLatin);

// Check if a character belongs to a Unicode block testChar = asc("A"); block = java:Character$UnicodeBlock::of(testChar); dump("Character 'A' belongs to: " & block);
// Access Character.UnicodeScript latin = java:Character$UnicodeScript::LATIN; dump(latin);

Class Reflection

Get Java Class objects for reflection purposes:

Implicit Class Access

// Get the Class object for HashMap
clazz = java.util.HashMap::class;
dump(clazz);

// Get class name and methods dump("Class name: " & clazz.getName()); dump("Simple name: " & clazz.getSimpleName());
// Get constructors constructors = clazz.getConstructors(); dump("Number of constructors: " & arrayLen(constructors));

Explicit Class Access

// Get Class object explicitly
clazz = java:java.util.HashMap::class;
dump(clazz);

// Get superclass superClass = clazz.getSuperclass(); dump("Superclass: " & superClass.getName());
// Get interfaces interfaces = clazz.getInterfaces(); dump("Implements " & arrayLen(interfaces) & " interfaces");
// Check if it's an interface, enum, etc. dump("Is interface: " & clazz.isInterface()); dump("Is enum: " & clazz.isEnum());

See also