Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I reflectively call a method on a Scala object from Java?

I have a scala object defined like the following:

package com.example

object Foo {
  def bar(): String = "Interesting Result"
}

I know that I can call Foo$.MODULE$.bar() from Java if Foo is in the build and runtime classpath, but in my situation Foo is not in the build classpath and may or may not be configured in the runtime classpath.

From my Java code I'd like to use reflection to call bar() if it is available on the runtime classpath, otherwise I'll fall back to a default implementation.

Is it possible to do this?

like image 899
David Carlson Avatar asked Jun 30 '11 02:06

David Carlson


2 Answers

You can do it with code that looks something like this:

package com.example.java;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Example {

  /**
   * Returns null or the result of calling a method on a scala object from java
   */
  public String callScalaFromJava(){
    String result = null;

    try {
      Class<?> clazz = Class.forName("com.example.Foo$"); // Note the trailing '$'
      Method method = clazz.getDeclaredMethod("bar");
      Field field = clazz.getField("MODULE$");
      Object instance = field.get(null);
      Object obj = method.invoke(instance, new Object[] {});

      if (obj instanceof String) {
        result = (String) obj);
      }

    } catch (Exception ex) {
      // SWALLOWING
    }
    return result;
  }
}
like image 194
David Carlson Avatar answered Oct 21 '22 19:10

David Carlson


The object Foo class is com.example.Foo$ so if you can just load that class, everything will go fine without using reflection:

try { 
    Class.forName("com.example.Foo$");
    String s = com.example.Foo$.MODULE$.bar();
    // ...
} catch (Exception ex) {
  String s = // fallback solution
  // ...
}
like image 45
paradigmatic Avatar answered Oct 21 '22 19:10

paradigmatic