Is it possible (how) to get the name of a method reference at Runtime Java? [duplicate]












1
















This question already has an answer here:




  • Printing debug info on errors with java 8 lambda expressions

    1 answer



  • Reflection type inference on Java 8 Lambdas

    5 answers



  • How to get the MethodInfo of a Java 8 method reference?

    11 answers




I've been using a lot of method references and lambdas recently, and wanted to know at runtime if i could print to screen the source of the lambda ie its name, simply for debugging reasons. I figured it might be possible using reflection, by calling getClass() within getName(), but I couldn't find a method with which to find the original source reference's name.



I have a functional interface such as:



@FunctionalInterface
public interface FooInterface {
// function etc etc irrelevant
public void method();

public default String getName() {
// returns the name of the method reference which this is used to define
}
}


then lets say i wish to test run the interface, and print the source of the functional interface to the screen.



public static void doStuff(FooInterface f) {
// prints the lambda name that is used to create f
System.out.println(f.getName());

// runs the method itself
f.method();
}


So that if i do this:



doStuff(Foo::aMethodReference);


it should print something like: "aMethodReference" to the screen, that way i can know, at runtime which methods are being run, in what order etc.



I'm quite doubtful that this is possible, considering that lambdas are not-quite-objects, but hey, i figured there could be a workaround. Furthermore, the eclipse debug tool just says its a lambda, without any other information, do lambda's retain any of this information? or is it all lost at Runtime?



Cheers. (I'm using JDK 11 if that makes any difference)










share|improve this question















marked as duplicate by Holger java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 21 '18 at 18:10


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.



















  • Although I haven't tried it with lambdas, you could use Thread.currentThread().getStackTrace() to get the current stack trace. The Elements returned offer a method getMethodName() that might print the right name. See this question.

    – tom1299
    Nov 20 '18 at 6:55


















1
















This question already has an answer here:




  • Printing debug info on errors with java 8 lambda expressions

    1 answer



  • Reflection type inference on Java 8 Lambdas

    5 answers



  • How to get the MethodInfo of a Java 8 method reference?

    11 answers




I've been using a lot of method references and lambdas recently, and wanted to know at runtime if i could print to screen the source of the lambda ie its name, simply for debugging reasons. I figured it might be possible using reflection, by calling getClass() within getName(), but I couldn't find a method with which to find the original source reference's name.



I have a functional interface such as:



@FunctionalInterface
public interface FooInterface {
// function etc etc irrelevant
public void method();

public default String getName() {
// returns the name of the method reference which this is used to define
}
}


then lets say i wish to test run the interface, and print the source of the functional interface to the screen.



public static void doStuff(FooInterface f) {
// prints the lambda name that is used to create f
System.out.println(f.getName());

// runs the method itself
f.method();
}


So that if i do this:



doStuff(Foo::aMethodReference);


it should print something like: "aMethodReference" to the screen, that way i can know, at runtime which methods are being run, in what order etc.



I'm quite doubtful that this is possible, considering that lambdas are not-quite-objects, but hey, i figured there could be a workaround. Furthermore, the eclipse debug tool just says its a lambda, without any other information, do lambda's retain any of this information? or is it all lost at Runtime?



Cheers. (I'm using JDK 11 if that makes any difference)










share|improve this question















marked as duplicate by Holger java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 21 '18 at 18:10


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.



















  • Although I haven't tried it with lambdas, you could use Thread.currentThread().getStackTrace() to get the current stack trace. The Elements returned offer a method getMethodName() that might print the right name. See this question.

    – tom1299
    Nov 20 '18 at 6:55
















1












1








1









This question already has an answer here:




  • Printing debug info on errors with java 8 lambda expressions

    1 answer



  • Reflection type inference on Java 8 Lambdas

    5 answers



  • How to get the MethodInfo of a Java 8 method reference?

    11 answers




I've been using a lot of method references and lambdas recently, and wanted to know at runtime if i could print to screen the source of the lambda ie its name, simply for debugging reasons. I figured it might be possible using reflection, by calling getClass() within getName(), but I couldn't find a method with which to find the original source reference's name.



I have a functional interface such as:



@FunctionalInterface
public interface FooInterface {
// function etc etc irrelevant
public void method();

public default String getName() {
// returns the name of the method reference which this is used to define
}
}


then lets say i wish to test run the interface, and print the source of the functional interface to the screen.



public static void doStuff(FooInterface f) {
// prints the lambda name that is used to create f
System.out.println(f.getName());

// runs the method itself
f.method();
}


So that if i do this:



doStuff(Foo::aMethodReference);


it should print something like: "aMethodReference" to the screen, that way i can know, at runtime which methods are being run, in what order etc.



I'm quite doubtful that this is possible, considering that lambdas are not-quite-objects, but hey, i figured there could be a workaround. Furthermore, the eclipse debug tool just says its a lambda, without any other information, do lambda's retain any of this information? or is it all lost at Runtime?



Cheers. (I'm using JDK 11 if that makes any difference)










share|improve this question

















This question already has an answer here:




  • Printing debug info on errors with java 8 lambda expressions

    1 answer



  • Reflection type inference on Java 8 Lambdas

    5 answers



  • How to get the MethodInfo of a Java 8 method reference?

    11 answers




I've been using a lot of method references and lambdas recently, and wanted to know at runtime if i could print to screen the source of the lambda ie its name, simply for debugging reasons. I figured it might be possible using reflection, by calling getClass() within getName(), but I couldn't find a method with which to find the original source reference's name.



I have a functional interface such as:



@FunctionalInterface
public interface FooInterface {
// function etc etc irrelevant
public void method();

public default String getName() {
// returns the name of the method reference which this is used to define
}
}


then lets say i wish to test run the interface, and print the source of the functional interface to the screen.



public static void doStuff(FooInterface f) {
// prints the lambda name that is used to create f
System.out.println(f.getName());

// runs the method itself
f.method();
}


So that if i do this:



doStuff(Foo::aMethodReference);


it should print something like: "aMethodReference" to the screen, that way i can know, at runtime which methods are being run, in what order etc.



I'm quite doubtful that this is possible, considering that lambdas are not-quite-objects, but hey, i figured there could be a workaround. Furthermore, the eclipse debug tool just says its a lambda, without any other information, do lambda's retain any of this information? or is it all lost at Runtime?



Cheers. (I'm using JDK 11 if that makes any difference)





This question already has an answer here:




  • Printing debug info on errors with java 8 lambda expressions

    1 answer



  • Reflection type inference on Java 8 Lambdas

    5 answers



  • How to get the MethodInfo of a Java 8 method reference?

    11 answers








java lambda reflection java-8 method-reference






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 2:45









Federico Peralta Schaffner

23.1k43676




23.1k43676










asked Nov 20 '18 at 6:47









JohnJohn

757




757




marked as duplicate by Holger java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 21 '18 at 18:10


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.









marked as duplicate by Holger java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 21 '18 at 18:10


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.















  • Although I haven't tried it with lambdas, you could use Thread.currentThread().getStackTrace() to get the current stack trace. The Elements returned offer a method getMethodName() that might print the right name. See this question.

    – tom1299
    Nov 20 '18 at 6:55





















  • Although I haven't tried it with lambdas, you could use Thread.currentThread().getStackTrace() to get the current stack trace. The Elements returned offer a method getMethodName() that might print the right name. See this question.

    – tom1299
    Nov 20 '18 at 6:55



















Although I haven't tried it with lambdas, you could use Thread.currentThread().getStackTrace() to get the current stack trace. The Elements returned offer a method getMethodName() that might print the right name. See this question.

– tom1299
Nov 20 '18 at 6:55







Although I haven't tried it with lambdas, you could use Thread.currentThread().getStackTrace() to get the current stack trace. The Elements returned offer a method getMethodName() that might print the right name. See this question.

– tom1299
Nov 20 '18 at 6:55














1 Answer
1






active

oldest

votes


















1














As you're saying that you only need this for debugging purposes, here is a trick (i.e. a dirty hack) that will allow you to do what you want.



First of all, your functional interface must be Serializable:



@FunctionalInterface
public interface FooInterface extends Serializable {

void method();
}


Now, you can use this undocumented, internal-implementation-dependent and extremely risky code to print some information about the method reference targeted to your FooInterface functional interface:



@FunctionalInterface
public interface FooInterface extends Serializable {

void method();

default String getName() {
try {
Method writeReplace = this.getClass().getDeclaredMethod("writeReplace");
writeReplace.setAccessible(true);
SerializedLambda sl = (SerializedLambda) writeReplace.invoke(this);
return sl.getImplClass() + "::" + sl.getImplMethodName();
} catch (Exception e) {
return null;
}
}
}


When you call this method:



doStuff(Foo::aMethodReference);


You'll see the following output:



package/to/the/class/Foo::aMethodReference


Note 1: I've seen this approach in this article by Peter Lawrey.



Note 2: I've tested this with openjdk version "11" 2018-09-25 and also with java version "1.8.0_192".






share|improve this answer
























  • hmmm, i really like this answer, but i get the exception: java.lang.NoSuchMethodException: transaction.SaleBuilder$TransactionBuilder$$Lambda$288/0x000000010040f040.writeReplace()

    – John
    Nov 21 '18 at 0:00













  • if i can get this to work, this is exactly what i am after

    – John
    Nov 21 '18 at 0:01











  • WAIT, i havent made it serializable

    – John
    Nov 21 '18 at 0:04






  • 1





    YES, it works! thankyou, you are amazing cheers

    – John
    Nov 21 '18 at 0:05






  • 1





    Well noted, though I merely need this for debugging, cheers.

    – John
    Nov 21 '18 at 0:58


















1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














As you're saying that you only need this for debugging purposes, here is a trick (i.e. a dirty hack) that will allow you to do what you want.



First of all, your functional interface must be Serializable:



@FunctionalInterface
public interface FooInterface extends Serializable {

void method();
}


Now, you can use this undocumented, internal-implementation-dependent and extremely risky code to print some information about the method reference targeted to your FooInterface functional interface:



@FunctionalInterface
public interface FooInterface extends Serializable {

void method();

default String getName() {
try {
Method writeReplace = this.getClass().getDeclaredMethod("writeReplace");
writeReplace.setAccessible(true);
SerializedLambda sl = (SerializedLambda) writeReplace.invoke(this);
return sl.getImplClass() + "::" + sl.getImplMethodName();
} catch (Exception e) {
return null;
}
}
}


When you call this method:



doStuff(Foo::aMethodReference);


You'll see the following output:



package/to/the/class/Foo::aMethodReference


Note 1: I've seen this approach in this article by Peter Lawrey.



Note 2: I've tested this with openjdk version "11" 2018-09-25 and also with java version "1.8.0_192".






share|improve this answer
























  • hmmm, i really like this answer, but i get the exception: java.lang.NoSuchMethodException: transaction.SaleBuilder$TransactionBuilder$$Lambda$288/0x000000010040f040.writeReplace()

    – John
    Nov 21 '18 at 0:00













  • if i can get this to work, this is exactly what i am after

    – John
    Nov 21 '18 at 0:01











  • WAIT, i havent made it serializable

    – John
    Nov 21 '18 at 0:04






  • 1





    YES, it works! thankyou, you are amazing cheers

    – John
    Nov 21 '18 at 0:05






  • 1





    Well noted, though I merely need this for debugging, cheers.

    – John
    Nov 21 '18 at 0:58
















1














As you're saying that you only need this for debugging purposes, here is a trick (i.e. a dirty hack) that will allow you to do what you want.



First of all, your functional interface must be Serializable:



@FunctionalInterface
public interface FooInterface extends Serializable {

void method();
}


Now, you can use this undocumented, internal-implementation-dependent and extremely risky code to print some information about the method reference targeted to your FooInterface functional interface:



@FunctionalInterface
public interface FooInterface extends Serializable {

void method();

default String getName() {
try {
Method writeReplace = this.getClass().getDeclaredMethod("writeReplace");
writeReplace.setAccessible(true);
SerializedLambda sl = (SerializedLambda) writeReplace.invoke(this);
return sl.getImplClass() + "::" + sl.getImplMethodName();
} catch (Exception e) {
return null;
}
}
}


When you call this method:



doStuff(Foo::aMethodReference);


You'll see the following output:



package/to/the/class/Foo::aMethodReference


Note 1: I've seen this approach in this article by Peter Lawrey.



Note 2: I've tested this with openjdk version "11" 2018-09-25 and also with java version "1.8.0_192".






share|improve this answer
























  • hmmm, i really like this answer, but i get the exception: java.lang.NoSuchMethodException: transaction.SaleBuilder$TransactionBuilder$$Lambda$288/0x000000010040f040.writeReplace()

    – John
    Nov 21 '18 at 0:00













  • if i can get this to work, this is exactly what i am after

    – John
    Nov 21 '18 at 0:01











  • WAIT, i havent made it serializable

    – John
    Nov 21 '18 at 0:04






  • 1





    YES, it works! thankyou, you are amazing cheers

    – John
    Nov 21 '18 at 0:05






  • 1





    Well noted, though I merely need this for debugging, cheers.

    – John
    Nov 21 '18 at 0:58














1












1








1







As you're saying that you only need this for debugging purposes, here is a trick (i.e. a dirty hack) that will allow you to do what you want.



First of all, your functional interface must be Serializable:



@FunctionalInterface
public interface FooInterface extends Serializable {

void method();
}


Now, you can use this undocumented, internal-implementation-dependent and extremely risky code to print some information about the method reference targeted to your FooInterface functional interface:



@FunctionalInterface
public interface FooInterface extends Serializable {

void method();

default String getName() {
try {
Method writeReplace = this.getClass().getDeclaredMethod("writeReplace");
writeReplace.setAccessible(true);
SerializedLambda sl = (SerializedLambda) writeReplace.invoke(this);
return sl.getImplClass() + "::" + sl.getImplMethodName();
} catch (Exception e) {
return null;
}
}
}


When you call this method:



doStuff(Foo::aMethodReference);


You'll see the following output:



package/to/the/class/Foo::aMethodReference


Note 1: I've seen this approach in this article by Peter Lawrey.



Note 2: I've tested this with openjdk version "11" 2018-09-25 and also with java version "1.8.0_192".






share|improve this answer













As you're saying that you only need this for debugging purposes, here is a trick (i.e. a dirty hack) that will allow you to do what you want.



First of all, your functional interface must be Serializable:



@FunctionalInterface
public interface FooInterface extends Serializable {

void method();
}


Now, you can use this undocumented, internal-implementation-dependent and extremely risky code to print some information about the method reference targeted to your FooInterface functional interface:



@FunctionalInterface
public interface FooInterface extends Serializable {

void method();

default String getName() {
try {
Method writeReplace = this.getClass().getDeclaredMethod("writeReplace");
writeReplace.setAccessible(true);
SerializedLambda sl = (SerializedLambda) writeReplace.invoke(this);
return sl.getImplClass() + "::" + sl.getImplMethodName();
} catch (Exception e) {
return null;
}
}
}


When you call this method:



doStuff(Foo::aMethodReference);


You'll see the following output:



package/to/the/class/Foo::aMethodReference


Note 1: I've seen this approach in this article by Peter Lawrey.



Note 2: I've tested this with openjdk version "11" 2018-09-25 and also with java version "1.8.0_192".







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 20 '18 at 16:28









Federico Peralta SchaffnerFederico Peralta Schaffner

23.1k43676




23.1k43676













  • hmmm, i really like this answer, but i get the exception: java.lang.NoSuchMethodException: transaction.SaleBuilder$TransactionBuilder$$Lambda$288/0x000000010040f040.writeReplace()

    – John
    Nov 21 '18 at 0:00













  • if i can get this to work, this is exactly what i am after

    – John
    Nov 21 '18 at 0:01











  • WAIT, i havent made it serializable

    – John
    Nov 21 '18 at 0:04






  • 1





    YES, it works! thankyou, you are amazing cheers

    – John
    Nov 21 '18 at 0:05






  • 1





    Well noted, though I merely need this for debugging, cheers.

    – John
    Nov 21 '18 at 0:58



















  • hmmm, i really like this answer, but i get the exception: java.lang.NoSuchMethodException: transaction.SaleBuilder$TransactionBuilder$$Lambda$288/0x000000010040f040.writeReplace()

    – John
    Nov 21 '18 at 0:00













  • if i can get this to work, this is exactly what i am after

    – John
    Nov 21 '18 at 0:01











  • WAIT, i havent made it serializable

    – John
    Nov 21 '18 at 0:04






  • 1





    YES, it works! thankyou, you are amazing cheers

    – John
    Nov 21 '18 at 0:05






  • 1





    Well noted, though I merely need this for debugging, cheers.

    – John
    Nov 21 '18 at 0:58

















hmmm, i really like this answer, but i get the exception: java.lang.NoSuchMethodException: transaction.SaleBuilder$TransactionBuilder$$Lambda$288/0x000000010040f040.writeReplace()

– John
Nov 21 '18 at 0:00







hmmm, i really like this answer, but i get the exception: java.lang.NoSuchMethodException: transaction.SaleBuilder$TransactionBuilder$$Lambda$288/0x000000010040f040.writeReplace()

– John
Nov 21 '18 at 0:00















if i can get this to work, this is exactly what i am after

– John
Nov 21 '18 at 0:01





if i can get this to work, this is exactly what i am after

– John
Nov 21 '18 at 0:01













WAIT, i havent made it serializable

– John
Nov 21 '18 at 0:04





WAIT, i havent made it serializable

– John
Nov 21 '18 at 0:04




1




1





YES, it works! thankyou, you are amazing cheers

– John
Nov 21 '18 at 0:05





YES, it works! thankyou, you are amazing cheers

– John
Nov 21 '18 at 0:05




1




1





Well noted, though I merely need this for debugging, cheers.

– John
Nov 21 '18 at 0:58





Well noted, though I merely need this for debugging, cheers.

– John
Nov 21 '18 at 0:58





Popular posts from this blog

Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

ComboBox Display Member on multiple fields

Is it possible to collect Nectar points via Trainline?