Skip to content

Instantly share code, notes, and snippets.

@walterhiggins
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save walterhiggins/8de7a93e8b57e62aa16d to your computer and use it in GitHub Desktop.
Save walterhiggins/8de7a93e8b57e62aa16d to your computer and use it in GitHub Desktop.
Trying to call an overloaded constructor with vararg parameters.
var cmRecipe = Packages.net.canarymod.api.recipes.CraftingRecipe;
var cmRecipeRow = Packages.net.canarymod.api.recipes.RecipeRow;
// see https://ci.visualillusionsent.net/job/CanaryLib/javadoc/net/canarymod/api/inventory/recipes/CraftingRecipe.html
var rows = [
new cmRecipeRow("ESW", [ enderPearl, stick, string]),
new cmRecipeRow("SEW", [ stick, enderPearl, string]),
new cmRecipeRow("ESW", [ enderPearl, stick, string])
];
var signature = "(net.canarymod.api.inventory.Item, net.canarymod.api.inventory.recipes.RecipeRow[])";
var enderBowRecipe = new cmRecipe[signature]( enderBow, rows);
@walterhiggins
Copy link
Author

When this code is executed I get the following error:

line #22 : null is not a function
signature = "(net.canarymod.api.inventory.Item, net.canarymod.api.inventory.recipes.RecipeRow[])";
> var enderBowRecipe = new cmRecipe[signature]( enderBow, rows);
 server.addRecipe(enderBowRecipe);

If I execute without an explicit signature...

var enderBowRecipe = new cmRecipe( enderBow, rows); 

I get this error...

java.lang.NoSuchMethodException: Can't unambiguously select between fixed arity signatures [(net.canarymod.api.inventory.Item, net.canarymod.api.inventory.Item[]), (net.canarymod.api.inventory.Item, net.canarymod.api.inventory.recipes.RecipeRow[])] of the method net.canarymod.api.inventory.recipes.CraftingRecipe. for argument types [net.canarymod.api.inventory.CanaryItem, jdk.nashorn.internal.objects.NativeArray]

@walterhiggins
Copy link
Author

Does this mean that if a Java method has two overloads each of which have the same number of parameters and both methods have variable argument parameters, then explicit overload resolution will fail?

public class A {
    public A( B... ) { 
    }
    public A( C... ) { 
    }
}
 var a = new A( [ new B(), new B() ] ) ;// fails
 var a = new A( [ new C(), new C() ] ); // fails
 var a = new A["(B[])"]( [ new B(), new B() ]) ; // also fails as it can't be resolved!

@szegedi
Copy link

szegedi commented Oct 2, 2014

You have several options (sorry, I'll be typing these off the top of my head, not trying them out myself, so minor errors are possible).

1. Explicit constructor overload selection

This is something that will only work in Java 8u40 (it's already available in the early access builds). However, you'd use the explicit signature as part of the type name on the package, and not as a property of the constructor object itself:

  var cmRecipeCtor = Packages.net.canarymod.api.recipes["CraftingRecipe(Item, RecipeRow[])"];

(Notice, by the way, that you can use unqualified type names for the signature as Nashorn is smart enough to know that you're selecting among a finite number of overloads and can figure out what you meant. You would only need to use qualified type names in case two overloads could only be distinguished by parameter types in the same position that have the same unqualified name but different packages. Which is practically (hopefully) never.)

2. Coerce the array argument into explicit Java array type

This solution is available since Nashorn was first released in Java 8; you just use Java.to with a specific Java array type:

  var cmRecipeRowArray = Java.type("net.canarymod.api.recipes.RecipeRow[]");
  var enderBowRecipe = new cmRecipe(enderBow, Java.to(rows, cmRecipeRowArray));

Hope this helps,
Attila.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment