Unable to iterate over Java object properties using for (var p in object) construct

Attila Szegedi attila.szegedi at oracle.com
Tue Mar 11 10:00:08 UTC 2014


Hi Walter,

thanks for trying out Nashorn and for your feedback. Nashorn's Java interop is different from Rhino's. The object models of Java and JavaScript are sufficiently different that a lot of functionality isn't straightforward to implement. We have chosen to err on the side of caution, and if we weren't convinced that something is the right way to do, we'd rather not implementing it than implement it in what we felt was the wrong way. We're open to community discussion - few months ago we have changed the way JS arrays are exposed to Java API after a discussion on this list.

That said, for…in over Java objects is not straightforward, as it'd require us to decide which of the properties are enumerable, and which are not. E.g. would we want every object to expose a property "class" since it has a getClass() method? While we're at it, for a property getter method (let's stay with getClass), should it expose both a "class" property and a "getClass" property which returns a callable representation of the method? (Right now, this is moot, as you can't call .apply and .call on Java methods, but we might change that in the future). If applied to an Java List or Map, should it only return indices/keys, or object methods and properties too? 

When we feel that the gap in the object model are too large, we'd rather provide an explicit API that people can use than implement implicit non-specification behavior that's papers over this too large gap, and that's not apparent from reading the source code. 

Speaking of such explicit APIs, there's a solution. Nashorn exposes a (non-ECMAScript standard) method Object.bindProperties() that allows you to get properties from one object, bind them to that object, and expose them in another object. E.g. if you want to iterate over methods and properties of an ArrayList:

var x = {}
var y = new java.util.ArrayList();
Object.bindProperties(x, y)
for(var i in x) {
    print(i);
}

will output:

getClass
wait
notifyAll
replaceAll
notify
remove
iterator
removeAll
stream
...

You can also selectively remove properties or otherwise edit the "x" object for further use (something you couldn't do with ArrayList proper - you couldn't remove its "stream" method etc.). 

Hope this helps. (Unfortunately, I can't think of a code construct that would works equally in both Rhino and Nashorn.)

Attila.


On Mar 8, 2014, at 10:25 PM, Walter Higgins <walter.higgins at gmail.com> wrote:

> In Java 7 I can iterate over the properties/methods of a Java object using
> this notation...
> 
> for (var p in javaObject) {
>  print(p);
> }
> 
> In java 8 this no longer works.
> 
> for (var p in javaObject) {
>  print(p);
> }
> 
> ...doesn't result in the for loop block being executed (there are no
> properties).
> 
> How can I iterate over the Java object properties in a consisted way
> between Java 6, 7 and 8?
> 
> -- 
> Walter Higgins
> Mobile: (+353) 086 8511600
> Website: http://walterhiggins.net/



More information about the nashorn-dev mailing list