Java consumer with return [duplicate] - java

This question already has answers here:
Why does a Java method reference with return type match the Consumer interface?
(2 answers)
Why doesn't for-each method in java not throw an exception when a Function type argument is passed instead of Consumer? [duplicate]
(3 answers)
Closed 4 years ago.
I don't understand why this code is working:
class Resource {
private Resource() {
System.out.println("created...");
}
public Resource op1() {
System.out.println("op1");
return this;
}
public Resource op2() {
System.out.println("op2");
return this;
}
private void close() {
System.out.println("clean up...");
}
public static void use(Consumer<Resource> block) {
Resource resource = new Resource();
try {
block.accept(resource);
}
finally {
resource.close();
}
}
}
// method call
public class App
{
public static void main( String[] args )
{
Consumer<Resource> block = resource -> resource.op1().op2(); //here
Resource.use(block);
}
}
Consumer should accept one parameter and return void. But in this example Consumer take one parameter(resource) and return this parameter. Why it is working although I return resource instance instead of void?

Your Consumer<Resource> block = resource -> resource.op1().op2(); is equivalent to:
Consumer<Resource> block = new Consumer<Resource>() {
#Override
public void accept(Resource resource) {
resource.op1().op2(); // there is no return statement
}
};

Related

How can I find out which method a lambda applies to? [duplicate]

This question already has answers here:
Printing debug info on errors with java 8 lambda expressions
(2 answers)
How can I find the target of a Java8 method reference?
(2 answers)
Closed 3 years ago.
If a method in a library is called with a Java Lambda expression, these are often just wrapped method calls. Is it possible to find out what method that originally was, just for logging purposes? (Another question is about what object it applies to - this is specifically about the called method.)
class Foo {
private void doSomething() { ... }
public void doSomethingInTransaction() {
doInTransaction(this::doSomething);
}
private void doInTransaction(Runnable run) { ... }
}
When calling doSomethingInTransaction() the method doInTransaction is actually called with an Object of type Runnable. It would sometimes be nice to log the name and class of the method that was passed here (that is, Foo.doSomething), as well as the object. Is it somehow possible to find out what that was via reflection or whatnot? If that requires specific Java versions, that'd be an interesting answer, too.
(UPDATE: please note that this is not a duplicate of the related question Java 8 - how to access object and method encapsulated as lambda since I'm mostly asking for the method that is encapsulated there. That wasn't asked there.)
The following example shows how to get the method reference name from the runnable. As explained in the comments, the code may be unnecesserarily complex and only works for certain cases (including the one in the question). Also, it makes certain assumptions that don't work in the general case.
Example class:
public class Test {
public void callingMethod() {
this.acceptingMethod(this::methodReferenceMethod);
}
public void acceptingMethod(final Runnable runnable) {
final String name = Util.getRunnableName(runnable, "acceptingMethod");
System.out.println("Name is " + name);
}
public void methodReferenceMethod() {
}
public static void main(final String[] args) {
new Test().callingMethod();
}
}
Now the actual magic here:
class Util {
public static String getRunnableName(final Runnable runnable, final String calledMethodName) {
final String callSiteMethodName = getCallSiteMethodNameNotThreadSafe();
final Class<?> callSiteClass = getDeclaringClass(runnable);
final String runnableName = extractRunnableName(callSiteClass, callSiteMethodName, calledMethodName);
return runnableName;
}
private static String extractRunnableName(
final Class<?> callSiteClass,
final String callSiteMethodName,
final String calledMethodName) {
try {
final AtomicReference<String> result = new AtomicReference<>(null);
final ClassReader cr = new ClassReader(callSiteClass.getName());
final TraceClassVisitor traceVisitor = new TraceClassVisitor(new PrintWriter(System.out));
cr.accept(new CheckClassAdapter(Opcodes.ASM7, traceVisitor, false) {
#Override
public MethodVisitor visitMethod(final int access, final String name, final String descriptor, final String signature, final String[] exceptions) {
if (!name.equals(callSiteMethodName)) {
return super.visitMethod(access, calledMethodName, descriptor, signature, exceptions);
}
return new CheckMethodAdapter(Opcodes.ASM7, super.visitMethod(access, name, descriptor, signature, exceptions), new HashMap<>()) {
#Override
public void visitInvokeDynamicInsn(final String name, final String descriptor, final Handle bootstrapMethodHandle, final Object... bootstrapMethodArguments) {
final String invokeDynamic = ((Handle) bootstrapMethodArguments[1]).getName();
result.set(invokeDynamic);
}
};
}
}, 0);
return result.get();
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
public static String getCallSiteMethodNameNotThreadSafe() {
final int depth = 4;
return Thread.currentThread().getStackTrace()[depth].getMethodName();
}
public static Class<?> getDeclaringClass(final Runnable runnable) {
return Arrays.stream(runnable.getClass().getDeclaredFields())
.filter(f -> f.getName().equals("arg$1"))
.map(f -> {
f.setAccessible(true);
try {
return f.get(runnable).getClass();
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException(e);
}
})
.findFirst()
.orElseThrow(IllegalStateException::new);
}
}
The output is as expected "Name is methodReferenceMethod". I would probably never use this in any project, but I guess it is possible. Also, this only works for the given example, as there is only one INVOKEVIRTUAL in the calling method. For the general case, one would need to adjust the checkMethodVisitor and filter the calls to the "calledMethodName" only. Lastly, the code to get the calling method uses a fixed index for the stack trace element, which also does not generalize well.

Non-static method referenced from a static context [duplicate]

This question already has answers here:
What is the reason behind "non-static method cannot be referenced from a static context"? [duplicate]
(13 answers)
Closed 8 years ago.
I have two errors both the same and they follow below:
class FBox {//...}
class FBPlayer
{
//Initialized instances
FBox game = new FBox();
**FBPillar pillar = new FBPillar();**
**FBObjects objects = new FBObjects();**
//Lots o Properties...
public boolean get_Alive() { return this.b_PlayerAlive; }
public void set_Alive(boolean alive) { this.b_PlayerAlive = alive; }
//My Error ridden Method
public void checkCollision()
{
if(get_YPos() >= **objects**.get_Ground())
^My Error was incorrect name for my instance
{
set_Alive(false);
}
else if(get_Bounds().intersects(**pillar**.get_Bounds()))
^My Error was incorrect name for my instance
{
set_Alive(false);
}
}
class FBPillar
{
public int get_Bounds() {return 'the variable'; }
}
class FBObjects
{
public int get_Ground() {return 'the variable'; }
}
The error is in the if statement as well as the else if statement
When i run it it returns the error:
FBox.java:178: error: non-static method get_Bounds() cannot be referenced from a static context
else if(get_Bounds().intersects(**FBPillar**.get_Bounds()))
The same error for the if statement but with FBObjects.get_Ground())
^
Whose bounds are you talking about? You probably mean
if (get_Bounds().intersects(pillar.get_Bounds())) {
…
}
I'd also add that
FBPlayer player = new FBPlayer();
means that a player contains a player, which is probably isn't what you intended.

Get generic type T in Java? [duplicate]

This question already has answers here:
Get generic type of class at runtime
(30 answers)
Closed 8 years ago.
I have this class:
public class ActorFixture<T>
{
public T actor;
public String fixture;
public ActorFixture() {}
public ActorFixture(T actor, String fixture)
{
this.actor = actor;
this.fixture = fixture;
}
public void setFixture(Fixture fa, Fixture fb)
{
Class<T> type;
if (type.isInstance(fa))
{
actor = type.cast(fa.getBody().getUserData());
fixture = (String)fa.getUserData();
}
else if (type.isInstance(fb))
{
actor = type.cast(fb.getBody().getUserData());
fixture = (String)fb.getUserData();
}
}
}
But I get a warning on 'type' because it's not initialized.
What's the correct way to check the type?
Try this:
Class<T> type = (Class<T>) this.actor.getClass();

passing method as parameter and getting error: java.lang.NoSuchMethodException: [duplicate]

This question already has answers here:
Java: NoSuchMethodException when method clearly exists
(4 answers)
Closed 9 years ago.
I am getting error: java.lang.NoSuchMethodException:
here is my code
public class ManageEnrollmentTest {
#Test
public void Test_Filter_By_Active() throws Exception{
assertTrue("Log in failed", Helper.LoginTest());
assertTrue("Activation failed", fitlerResults("Active"));
}
private Boolean fitlerResults(String dS){
Boolean isOk = false;
try{
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("$('#dType').val('36').change().trigger(\"liszt:updated\");;");
WebElement findButton = driver.findElement(By.id("findDealersBtn"));
findButton.click();
Method method = ManageEnrollmentTest.class.getMethod("verifyActive"); //////// Error
isOk = loadEnrollmentTablePageByPageAndVerify(method);
}
catch(Exception e){
e.printStackTrace();
isOk = false;
}
return isOk;
}
private Boolean loadEnrollmentTablePageByPageAndVerify(Method method){
return (Boolean)method.invoke(this);
}
//browse throw all dealers that are currently on page
private Boolean verifyActive(){
....
....
return isOk;
}
}
Your method is private but getMethod() only returns public method.You need to use getDeclaredMethod().
getMethod() - Returns a Method object that reflects the specified public member method of the class or interface represented by this Class object.

non static method cannot be referenced from static context - JAVA [duplicate]

This question already has answers here:
What is the reason behind "non-static method cannot be referenced from a static context"? [duplicate]
(13 answers)
Closed 10 years ago.
i am trying to pass the value t from one class to another, but before i even run the program i get non static method cannot be referenced from static context from this line of code :
t = (PrinterSettings.getT() * 60);
i am trying to get the value t from this code :
public int t = 1; //defualt value for amount of mintues in the future the job should wait untill sent
public int getT() {
return (t);
}
public void setT(int t) {
this.t = t;
}
what have i done wrong ? and how can i get t
EDIT :
Whole of my code where i get t from
public int t = 1; //defualt value for amount of seconds in the future the job should wait untill sent
public int getT() {
return (t);
}
public void setT(int t) {
this.t = t;
}
and this is the class that i am using that calls t from the above class to use:
public class DealyTillPrint {
public int t;
public String CompletefileName;
private String printerindx;
private static int s;
private static int x;
public static int SecondsTillRelase;
public void countDown() {
System.out.println("Countdown called");
s = 1; // interval
t = ((new PrinterSettings().getT()) * 60); //(PrinterSettings.SecondsTillRelase); // number of seconds
System.out.println("t is : " + t);
while (t > 0) {
System.out.println("Printing in : " + t);
try {
Thread.sleep(s * 1000);
} catch (Exception e) {
}
t--;
}
and here is where i set t using a spinner
<p:spinner min="1" max="1000" value="#{printerSettings.t}" size ="1">
<p:ajax update="NewTime"/>
</p:spinner>
You're using PrinterSettings.getT() but you can't do that because PrinterSettings is a class and the getT() method is for the object. You need to create an object of PrinterSettings first, then you can call getT().
PrinterSettings myObjectOfPrinterSettings = new PrinterSettings();
myObjectOfPrinterSettings.getT(); //this should work without the error
You can choose to do 1 of 2 things:
1) Make everything in your PrinterSettings file static (and make PrinterSettings static as well):
public static int t = 1;
public static int getT() {
return (t);
}
public static void setT(int t) {
this.t = t;
}
2) Don't change PrinterSettings, and just do this for your code:
//Put this somewhere at the beginning of your code:
PrinterSettings printerSettings = new PrinterSettings();
//Now have some code, which will include setT() at some point
//Then do this:
t = (printerSettings.getT() * 60);
In my opinion the latter would be more preferable.
EDIT: The edit that I just made is because if you don't keep a hold on the PrinterSettings variable that you were using, new-ing one up will have t be 1 in that new PrinterSettings object. Instead, make sure that you're instantiating an object of PrinterSettings at the beginning of your program, and just use that one the whole way through.
Instead of:
public int getT() {
return (t);
}
Write:
public static int getT() {
return (t);
}
This will solve your problem.
With this change you can access this method with its class name. As a class method.

Categories