Re: Potential to include java.time.* as a default import for Groovy 5

Jochen Theodorou <[email protected]> Mon, 2 Jun 2025 15:37:57 +0200
Newsgroups gmane.comp.lang.groovy.user
Message-ID <[email protected]>
I have a few points to mention here:

(1) we could consider, and that is combined with some danger, to import 
specific classes only. import foo.bar.X does not have the same problem 
as import foo.bar.* for the performance of the compiler. The danger of 
course is that if X is no longer there, it would fail compilation even.

(2) I was wondering if we should copy a feature from python here and 
allow for something like:

import package java.util as u
assert u.List == java.util.List

we already have class aliases, this would kind of complete the picture.

(3) and this is building on top of (2) and a bit on (1)... let me call 
them virtual packages:

import package groovy.vp.calendar as CAL

def calendar = new CAL.Calendar.Builder()
                 .set(CAL.Calendar.DAY_OF_MONTH, 11)
                 .set(CAL.Calendar.MONTH, Calendar.JULY)
                 .set(CAL.Calendar.YEAR, 2022)
                 .set(CAL.Calendar.HOUR, 8)
                 .set(CAL.Calendar.MINUTE, 30)
                 .set(CAL.Calendar.SECOND, 00)
                 .build()
def simpleDateFormat = new CAL.SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
println(simpleDateFormat.format(calendar.getTime()));

the idea is to have some container for classes, that is bound by 
feature, not by package structure. In this case SimpleDateFormat and 
Calender are both in the package groovy.vp.calendar, which is no real 
package and only contains the information that Calender is from 
java.util.Calender and SimpleDateFormat from java.format.SimpleDateFormat

Then you can have tailored packages like nio, nio2, collections, ...

(4) ha, so many crazy suggestions you think and you think I could not 
put one more on top? Wrong:

import groovy.vp.calendar.*

Now this is basically importing all classes from my virtual calendar 
package, namely Calendar and SimpleDateFormat.


Something general about class resolving...

I think I have to explain a bit about class resolving in Groovy in 
general. In the old times java was more dynamic than it was today. Back 
then You could have a jar X and a jar Y and both could declare classes 
in the same package. Practically this means if I import foo.* and do 
println Foo. I have to go through all class path elements and check if 
they define a package foo and if the package foo contains a class Foo - 
for each star import of course. And since it might be one time jar X and 
one time jar Y during compilation, heck both could define the class... 
it could be jar Z at runtime.

This is why in Groovy - which follows the tradition - additional star 
imports are expensive: # vanilla names * # classpath elements * # star 
imports. Only the situation is worse in Groovy since we decided to make 
classes and variables share the namespace. println foo could mean the 
class foo and we have to so maybe a 1000 search operations or a dynamic 
variable foo. Which is why lower case  class names are not valid in 
Groovy anymore.

Ah yes. A import of a class full name would be resolved with this cost: 
# classpath elements. Which is significantly lower.

In newer Java versions one package can only reside in one jar. It does 
no longer allow these things on the module path and the class path then 
stays empty. Also they imply that module path at compile time equals 
module path at runtime, so there are no classloader shenanigans to 
consider. No the compiler can take all module path elements and make a 
big map (vanilla name -> full class name | Error) once and resolve all 
vanilla names in one go. Or you could see it as if the java compiler 
replace java.util.* with full name imports from java.util, like 
java.util.List.

My suggestion (1) goes in the same direction and with (4) building on 
top of that you get a similar version with similar performance and 
without relying on the module system.

bye Jochen