Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala can't access Java inner class?

I have a java class that looks like this:

public class Constants {
    public class Commands {
        public static final String CreateOrder = "CreateOrder";
    }
}

I want to access "CreateOrder" constant, In java I can access it easily like this:

String co = Constants.Commands.CreateOrder

But in Scala this doesn't work why??? How can I access "CreateOrder" from Scala, I can't alter the Java code.

Thanks.

like image 593
Mustafa Avatar asked Oct 13 '13 13:10

Mustafa


People also ask

How do I access inner private class?

Accessing the Private Members Write an inner class in it, return the private members from a method within the inner class, say, getValue(), and finally from another class (from which you want to access the private members) call the getValue() method of the inner class.

Can inner class access?

As the inner class exists inside the outer class we must instantiate the outer class in order to instantiate the inner class. Hence, to access the inner class, first create an object of the outer class after that create an object of the inner class.

Can inner class Cannot access its own private variables?

It can access any private instance variable of the outer class. Like any other instance variable, we can have access modifier private, protected, public, and default modifier. Like class, an interface can also be nested and can have access specifiers.

Is it possible to override a inner classes?

No, you cannot override private methods in Java, private methods are non-virtual in Java and access differently than non-private one. Since method overriding can only be done on derived class and private methods are not accessible in a subclass, you just can not override them.


3 Answers

As far as I know, there is no way to do what you want in Scala.

But if you absolutely cannot change the Java code then you could resort to some reflection trickery.

val value = classOf[Constants#Commands].getDeclaredField("CreateOrder").get(null)
like image 160
sksamuel Avatar answered Oct 27 '22 00:10

sksamuel


I think a third alternative to reflection and instantiation is to write a small piece of Java glue code. Like

public class Glue {
    public static String createOrder() { return Constants.Commands.CreateOrder; }
}

Then from Scala you should be able to write Glue.createOrder.

like image 34
0__ Avatar answered Oct 26 '22 23:10

0__


From the Java Language Specification:

Inner classes may not declare static members, unless they are constant variables (§4.12.4), or a compile-time error occurs.

In the case of constant variables, you can use the Constants.Commands.CreateOrder syntax even though normally any reference to Constants.Commands would have to be associated with an instance of Constants, since it's not a static inner class.

This could be considered something of a crazy one-off syntactic special case in Java, and it's the kind of thing that the Scala language designers haven't bothered to bake into Scala's Java interoperability.

Your best bet (if your real Java class looks exactly like this) is to create an instance of Constants, at which point you can access the inner class's static field in a perfectly natural way:

scala> (new Constants).Commands.CreateOrder
res0: String = CreateOrder

If for some reason this isn't an option you'll have to go with the reflection-based approach in the other answer, unfortunately.

like image 31
Travis Brown Avatar answered Oct 27 '22 00:10

Travis Brown