Calling a lambda function later with different objects/arguments - java

I am a newbie in java functional interfaces so I want to see if this is possible and if not please explain me why not and what is possible in order to achieve my idea
I have these classes
public class A {
...
public String getInfo();
...
}
public class B {
...
public String getOtherInfo();
...
}
I want to pass the references to these functions to another object like this:
obj.init(A::getInfo)
obj.init(B::getOtherInfo)
so that later I can use/call these functions on different objects of type A or B inside the build functions:
obj.build(a1);
obj.build(a2);
...
obj.build(b1);
obj.build(b2);
PS1 I cannot use regular interfaces for this cause there are lot of getters and lots of classes similar to A which I want to use for this procedure and they are not related with one another
PS2 I try to avoid reflection cause you cannot trace the function calls
PS3 my example is not exactly working as is it throws this error: "non static method cannot be referenced from a static context"

A::get is a Java Method Reference. You should be able to store it for use later. As it's an instance method you'll need the instance object as well. So something like this might work:
Function<A,String> getFunction = A::get;
And whenever you need to use it you can do
//assuming you have an object instance of A which is a
getFunction.apply(a)
You can also pass it to other methods by declaring the method to take a functional parameter like this:
public void someOtherMethod(Function<A,String> param) {
//do whatever with param.
//invoke this with an instance of A when you're ready
param.apply(a);
}
Here's a reference that might help: https://www.baeldung.com/java-8-double-colon-operator

Made 2 mistakes
should have used Function<T, R> instead of Supplier
the error is thrown even if there is a slight mismatch of parameters even on the generic types. So an example of my function which accepts the Function parameter should be declared like this:
public <T extends Base> init (Function <T, String> f){
this.f = f;
}
and later I do something like:
public String build (A a){
return this.f.apply(a);
}
(so I had to make A, B implement some useless interface)

Related

Why can't Java infer the type of a lambda expression with a generic type parameter?

Given the following code:
abstract class Event {
}
class MyEvent extends Event {
}
interface EventSubscriber<T extends Event> {
void onMessage(T message);
Class<T> getMessageType();
}
interface MyEventSubscriber extends EventSubscriber<MyEvent> {
#Override
default Class<MyEvent> getMessageType() {
return MyEvent.class;
}
}
class SubscriberManager {
public void subscribe(EventSubscriber<? extends Event> subscriber) {
}
}
I would like to get access to the generic type parameter which an event subscriber holds via calling the getMessageType method.
I also would like to use the SubscriberManager by passing the lambda expressions to the subscribe method:
subscriberManager.subscribe((MyEvent event) -> {});
Unfortunately, the Java compiler can't infer the type of the lambda expression which is passed to the subscribe method, although it's pretty obvious to me that the type of the lambda could be deduced from the lambda's argument - MyEvent -> MyEventSubscriber. The Java compiler gives me the following error:
incompatible types: EventSubscriber is not a functional interface
multiple non-overriding abstract methods found in interface EventSubscriber
So I need to specify the type of the lambda expression or use the anonymous class in order to bypass this limitation:
MyEventSubscriber myEventSubscriber = (MyEvent event) -> {};
subscriberManager.subscribe(myEventSubscriber);
subscriberManager.subscribe(new MyEventSubscriber() {
#Override
public void onMessage(MyEvent message) {
}
});
I could add an overloaded method to the SubscriberManager class, remove the getMessageType method from the EventSubscriber interface (since we would know the actual type of the subscriber and therefore the message type it holds) and use the simple lambda expression I mentioned in the first code example, but it would make the whole code less 'polymorphic` I guess:
class SubscriberManager {
public void subscribe(EventSubscriber<? extends Event> subscriber) {
}
public void subscribe(MyEventSubscriber subscriber) {
}
}
The problem is that your EventSubscriber interface isn't a functional interface, as the error tells you: There are 2 methods to implement there. The fact that you've made an actual functional interface named MyEventSubscriber would mean that you want java to somehow intuit that this exists.
Java is not in the business of scouring the millions of classes in the classpath just to look and see if there's anything in that entire mess that may or may not work. I hope by putting it that way it's obvious why that is and why it'll never work that way.
Specifically: Because there's a lambda, java needs to target type it. To do this, java first checks the context surrounding the lambda: It checks the various methods named subscribe and notices there's only one, and it needs an argument of type EventSubscriber. It then target-types the lambda to this type, and immediately fails, as it is not a functional interface. There is no way for the compiler to figure it out it should be target-typing to MyEventSubscriber.
I did some toying around with using reflection to check the actual type, but that does not work; you'll have to find another way to tackle this problem.

Call Kotlin object with class delegation from Java as a static method

This may be a bit difficult to describe, so I'll try to give a concrete example of what I'm trying to do.
Suppose we have a Facade interface and class (in Java), like this:
interface FacadeInterface<T> {
void method(String from, String via);
}
class Facade<T> implements FacadeInterface<T> {
private Class<T> mClazz;
public Facade(Class<T> clazz) {
mClazz = clazz;
}
#Override
public void method(String from, String via) {
System.out.println("Method called from " + from + " via " + via);
}
}
In my applications, I need to have multiple singletons which hold an instance of the facade. The real facade has additional setup/config parameters but those are irrelevant here.
Before I started using kotlin, I would have a class which holds a static instance of the facade (not really a singleton, but in my case, it served a similar purpose) which proxied the calls to the facade, like this:
public class Singleton {
private static final FacadeInterface<String> sFacade = new Facade<>(String.class);
private Singleton() {
}
public static void method(String from, String via) {
sFacade.method(from, via);
}
}
Now, with Kotlin we have class delegates which allow me to write something like this:
object SingletonKt : FacadeInterface<String> by Facade(String::class.java)
This is great - no more boilerplate and I can call SingletonKt from Kotlin classes the same way I called the java Singleton:
Singleton.method("Kotlin", "Singleton")
SingletonKt.method("Kotlin", "SingletonKt")
But, a slight problem arises when I use SingletonKt from Java. Then I have to specify INSTANCE:
Singleton.method("Java", "Singleton");
SingletonKt.INSTANCE.method("Java", "SingletonKt");
I am aware of the #JvmStatic annotation, but the only place I can put it in the SingletonKt file without causing compile errors is right before FacadeInterface and it doesn't seem to do the trick.
Is there a way to set up this class delegate so that I can call it from Java as if it were a static method, without introducing the boilerplate of creating proxy methods for SingletonKt (which would defeat the purpose of the class delegate)?
It's sadly not possilble!
The Kotlin Delegation is a nice way to reduce boilerplate code. But it comes with the inability to actually access the delegate within the class body.
The second issue you're facing regarding #JvmStatic is actually more drastic to your cause than the first and also applies to you when implementing the delegation manually:
Override members cannot be '#JvmStatic' in object
So instead of exposing the method() through the INSTANCE only, you could delegate it to a staticMethod() on the object. This still differs from your intent, but comes close to it.
object SingletonKt : FacadeInterface<String> by Facade(String::class.java)
#JvmStatic fun staticMethod(from: String, via: String) = method(from, to)
}
I don't know if it is possible to have delegated methods as static methods inside an object in Kotlin.
However, as you are interested in creating singletons that proxy a class, you could use package-level constants in Kotlin:
val SingletonKt : FacadeInterface<String> = Facade(String::class.java)
Now, you can call SingletonKt.method just like you would in Java. Note that you need to use a static import in Java to be able to use the SingletonKt constant.
This also allows you to use features like lazy to only create the singleton (or, in this case, instance) when you need it.

Programmatically assess relationship between type variables in class hierarchy

Suppose I have a Java class hierarchy defined as follow:
interface Bar<T> {}
class Foo<A,B> implements Bar<B> {}
How can I programmatically assess (using reflection) that the type parameter of Bar in Foo is the second of foo's parameters and not the first (B instead of A)?
I've tried using TypeVariable#getName() in order to compare the names, but when I apply getGenericInterfaces() to Foo<A,B> I get Bar<T> and not Bar<B>
Solution (thanks to #LouisWasserman): use Foo.class.getGeenricInterfaces()[0].getActualTypeParameters() returns the correct TypeVariable (B instead of T, in the previous example)
well using TypeVariable#getName() return the type as it appears in the source code in your case it's normal to get Bar<T>. TypeVariable Doc
Using reflection in generic Classes can't help, because of Type Erasure. Erasure of Generic Types
I've the same issue in some personal projects, I tried to change the design of my class, have a look at the example below:
Instead of this:
public class Mapper<T> {
public Mapper(){
}
}
I used this:
public class Mapper {
private Class<?> entityClazz;
public Mapper(Class<?> entity){
this.entityClazz = entity
//Here I've donne all reflection issues i want !
}
}
You can use Class#isAssignableFrom() Doc to test assignability between Class Objects.
I hope this helps, good luck !

Re-using Java generic collections in Scala without trait Object

I'm trying to re-use a Java generic collection I wrote, looks a lot like this:
public class Blah<T>
implements List<T>
{
...
public void test(T[] array) {
...
}
...
}
When consumed from a Scala generic collection that uses the above, I'm getting a compilation error, where I notice that the Blah class method expects not T, but T with java.lang.Object!
Object MyStaticObject {
def test[T](array: Array[T]) = {
val x = new Blah[T]();
x.test(array) // <- error here: Overloaded method with alternatives test[T with java.lang.Object] ... cannot be applied
}
Is there a way to avoid this situation without re-writing the Blah class in Scala? (That works, but I have too much such Java code and rather not port the whole thing...)
Maybe perhaps some kind of implicit definition could come to the rescue?
Thanks!
Restricting def test[T <: AnyRef] does the trick.
Rightly so, the generic java method should not accept , e.g., an int[] (Array[Int]) parameter.
Blah[Int] will be taken as Blah<Integer>, Array[Int] is int[], which is not Integer[].

How to get arguments passed to method that called this method?

In Java, it is possible to get the class and method that called the current method (the method in which you get the StackTrace).
Can I get the arguments that were passed to the method that called this method?
I need this for debugging purposes.
Eg:
baseClass {
initialFunc(input) {
var modifiedInput = input + " I modified you";
otherClass.doSomething(modifiedInput);
}
}
otherClass {
doSomething(input) {
//GET THE ARGUMENTS PASSED TO THE METHOD OF THE CLASS THAT CALLED THIS METHOD
}
}
Can one get this information from the stacktrace, or are there other means?
(Note that I need to be able to do this in runtime and cannot actually change the source of baseClass, this is going to be a feature of my debugging class that does not know the source beforehand)
I don't believe this is possible using the standard Java API.
What you could do is to use AspectJ, place a point-cut at the calling method, save the arguments, place a point-cut at the called method and pass on the arguments.
Another option (slightly more advanced) is to use a custom, bytecode-rewriting, class loader that saves the original arguments, and passes them on as extra arguments to the next method. This would probably take a day or two to implement. Suitable frameworks are BCEL or ASM.
I think this could be possible, because input is out of scope but isn't yet accessible for garbage collection, so the value still exists, but unfortunately I don't believe there is an default API way to access it. This could be maybe possible with a custom implemented NDC (nested diagnostic context) for the logging approach.
I'm not sure why you'd ever want to do this in Java?
The only way I can think of is to create a custom wrapper object for the passed string, thus sending the reference to the wrapper instead of a new string each time.
I'd advice against it, though, since it clutters your original code, and makes it even more error prone.
Might this problem not be solved using a debugger, like the one built into eclipse, to inspect your state?
In my case, I needed to get a parameter value has been passed to a method in a certain stack frame to be used later within the execution flow
I used ThreadLocal to store it and when I needed it I was able to retrieve it at any point in code as I declared it as public static
here is a skeleton example
public static final ThreadLocal<SomeType> IMPORTANT_THREAD_LOCAL_FOR_BLA = ThreadLocal.withInitial(whatever);
methodWithImportantParam(SomeType importantValue){
// save it in the static threadLocal Field
this.IMPORTANT_THREAD_LOCAL_FOR_BLA.get()=importantValue;// code to set the value
// continue method logic
}
and somewhere in code where you need that value
YourClass.IMPORTANT_THREAD_LOCAL_FOR_BLA.get()
but make sure the execution flow that you set the value then you retrieve it
hope my answer add something valuable to this question
You can get name of caller method and its class, but you have to add some code in current method:
public static void main(String[] args) throws Exception {
call();
}
private static void call() {
Exception exception = new Exception();
for(StackTraceElement trace : exception.getStackTrace()){
System.out.println(trace.getMethodName());
}
}
This will print "call" and "main", methods name in called order (reverse).
This is possible using Reflection API !
public class StackTrace {
public static void main(String args[]) {
StackTrace st = new StackTrace();
st.func();
}
public void func() {
OtherClass os =new OtherClass();
os.getStackTrace(this);
}
}
class OtherClass {
void getStackTrace(Object obj) {
System.out.println(obj.getClass());
}
}

Categories