Java passing custom objects to Clojure - java

I have a .java file that will be called for its public String solve() method to answer a problem. The method receives project-defined Java class RP, which contains a collection of RF, which each contain a collection of RO, which each contain several RA which, finally, boil down to String, String pairs (a name and a value). My question is, (how) can I have that solve() method pass its RP object to Clojure where I believe I can do all the work to generate a solution more effectively, and eventually return a String solution back?
EDIT: What I'm looking for is some way of saying, String answer = toClojure(RP); and in Clojure I'll be able to do the equivalent of RP.getRF().getRO().getRA().getName(), where each of these functions is defined in the Java classes.

Just pass it the object reference, same as you would pass it to a java method. Clojure doesn't need any special magic to receive java objects.

Related

How to define an order for a list of methods in java?

One reason would be to get a specific order that methods are to be called.
I would guess that pattern language would be used for this. This can be done in JavaScript but what is the solution in Java, can it be done?
if you want that the user calls a specific sequence of methods, put this workflow into a method and make this method the only accessible point of entry for the user.
otherwise there is no need in java to define a specific order of methods in a source file.
This is just a sketch right now, have not tested yet!
put all the method names in a String[]
create a for loop to traverse the array
Then substitute the methodname for the array member in the code in the next clue:
How do I invoke a Java method when given the method name as a string?

Using scala object inside java?

In my java code, I am calling a method, from a class which is defined in Scala, and I want to use one of its methods in java. Here is how I call it and it works fine.
Seq<SomeObjectType> variableName = ScalaClass.MethodInTheScalaClass();
I can call this function in java in this form, but since I am calling this method from a compiled package, I can't see what it going on (and therefore I can't change it).
The problem now is that, I don't know how to iterate over the "variableName" in java (since Seq is a scala type).
How can I iterate over variableName or convert it to a Java object (e.g. List)?
Try this:
java.util.List<SomeObjectType> res =
scala.collection.JavaConverters$.MODULE$.seqAsJavaListConverter(variableName).asJava();
You could get converters list in JavaConverters documentation.
You should use JavaConverters$.MODULE$ to get JavaConverters object from Java.

Return an Object Array from Java to C++

I have an array of a custom class in Java that contains two String attributes. I call a Java function from C++ via JNI that returns a array of this class. Can anyone show me how I can access this array in the C++ code?
Kind Regards
You can use CallStaticObjectMethod follow the link, its a nice article for problem you are looking

Is it possible in Java to override 'toString' for an Objects array?

Is it possible in Java to override a toString for an Objects array?
For example, let's say I created a simple class, User (it doesn't really matter which class is it since this is a general question). Is it possible that, once the client creates a User[] array and the client uses System.out.print(array), it won't print the array's address but instead a customized toString()?
PS: of course I can't just override toString() in my class since it's related to single instances.
No. Of course you can create a static method User.toString( User[] ), but it won't be called implicitly.
You can use Arrays.toString(Object[] a); which will call the toString() method on each object in the array.
Edit (from comment):
I understand what it is you're trying to achieve, but Java doesn't support that at this time.
In Java, arrays are objects that are dynamically created and may be assigned to variables of type Object. All methods of class Object may be invoked on an array. See JLS Ch10
When you invoke toString() on an object it returns a string that "textually represents" the object. Because an array is an instance of Object that is why you only get the name of the class, the # and a hex value. See Object#toString
The Arrays.toString() method returns the equivalent of the array as a list, which is iterated over and toString() called on each object in the list.
So while you won't be able to do System.out.println(userList); you can do System.out.println(Arrays.toString(userList); which will essentially achieve the same thing.
You can create a separate class containing the array, and override toString().
I think the simplest solution is to extend the ArrayList class, and just override toString() (for example, UserArrayList).
The only way you can do this is to re-compile Object.toString() and add instanceof clauses.
I had requested a change in Project Coin to handle arrays in a more object orientated way. I felt that it's too much for beginners to learn all the functionality you need in Array, Arrays and 7 other helper classes which are commonly used.
I think in the end it was concluded that to make arrays properly object orientated is a non-trivial task which will be pushed back to Java 9 or beyond.
Try this
User[] array = new User[2];
System.out.println(Arrays.asList(array));
of course if you have customized user.toString() method
You cannot do that. When you declare an array, then Java in fact creates a hidden object of type Array. It is a special kind of class (for example, it supports the index access [] operator) which normal code cannot directly access.
If you wanted to override toString(), you would have to extend this class. But you cannot do it, since it is hidden.
I think it is good to be it this way. If one could extend the Array class, then one could add all kinds of methods there. And when someone else manages this code, they see custom methods on arrays and they are "WTF... Is this C++ or what?".
Well, you can try to wrap all calls to Object.toString with an AspectJ around advice and return the desired output for arrays. However, I don't think it's a good solution :)

How to pass a typed collection from clojure to java?

I know the basics of clojure/java interop: calling java from clojure and vice versa. However, I was not able to return a typed collection from clojure to java. I am trying to see something of that nature List<TypedObject> from the java code which is calling into clojure.
Java Object:
public class TypedObject {
private OtherType1 _prop1;
public OtherType1 getProp1() {
return _prop1;
}
public void setProp1(OtherType1 prop1) {
_prop1 = prop1;
}
}
CLojure method:
(defn -createListOfTypedObjects
"Creates and returns a list of TypedObjects"
[input]
;Do work here to create and return list of TypedObjects
[typedObj1, typedObj2, typedObj3])
(:gen-class
:name some.namespace
:methods [createListofTypedObjects[String] ????])
Let us consider that I am writing an API using clojure, which is to be distributed as a jar file, to be used from java. My question was really how to what to pass in place of the ???? questions marks above inside the :gen-class for AOT, so that a programmer writing a piece of code in java using my api, can have the appropriate intellisense / code completion (i.e.: createListofTypedObjects() returns List<TypedObject>) from within eclipse for example.
The others are right that Clojure doesn't ensure the types of elements in returned collections, etc. (Actually, the JVM doesn't ensure the types of elements in collections, either – that's handled entirely by javac.)
However, I can see the value of providing an API to other Java programmers that specifies an interface that declares that return values (or parameters) parameterized in various ways; this is especially attractive if one is looking to use Clojure in an existing Java environment without making waves.
This currently requires a two step process:
define a separate interface (in Java!) that specifies the parameterized types as you like
define your gen-class namespace (or proxy or reify instance) such that it implements that interface
(Clojure does provide a definterface form that would allow you to avoid the separate Java interface definition, but definterface, just like the rest of Clojure, does not provide for specifying parameterized types. Maybe someday... :-))
e.g.
public interface IFoo {
List<TypedObject> createListOfTypedObjects ();
}
and then your gen-class namespace:
(ns your.ns.FooImpl
(:gen-class
:implements [IFoo]))
(defn -createListOfTypedObjects
[]
[typedObj1, typedObj2, typedObj3])
When your users create instances of FooImpl, they'll e.g. get code completion indicating that the method returns List<TypedObject> rather than Object or the unparameterized List type.
If you're using sane build tools (e.g. maven, gradle, or properly-configured ant), then you can put the Java interface in your Clojure project, and the cross-language dependency will be taken care of.
If you're trying to pass something like List<String> to a java method, then you don't need to worry about it. The type parameter (e.g., String) is only used to by the javac compiler, so any List will work just fine at runtime.
On the other hand if you're trying to pass an array of a particular object type (e.g., String[]), then you can use the various -array functions:
user=> (make-array String 10) ; an empty String array
#<String[] [Ljava.lang.String;#78878c4c>
user=> (into-array ["foo" "bar"]) ; array type inferred from first element
#<String[] [Ljava.lang.String;#743fbbfc>
user=> (into-array Number [1.2 5 7N]) ; explicit type array
#<Number[] [Ljava.lang.Number;#7433b121>
You don't need to worry about generics (typed collections) in Clojure. Generics are really just type hints to the Java compiler. In a running Java program, List<String> is effectively the same as List<Object>.
So, for example, a Clojure vector containing Strings is already a List<String> with no conversion needed.

Categories