I have a Spring Boot test class where I’ve defined a private method. I also have a helper Service class which has a simple method that accepts a Runnable and executes it.
My expectation was that the private method from the test class could not be passed and run as a Runnable in the Service class because it’s private. However, in practice, the method seems to be running without any issues.
Here’s a simplified example of what I’m doing:
@SpringBootTest
public class MyTest {
private void myPrivateMethod() {
// Some code here
}
@Autowired
private MyService myService;
@Test
public void myTest() {
myService.runRunnable(() -> myPrivateMethod());
}
}
@Service
public class MyService {
public void runRunnable(Runnable r) {
r.run();
}
}
I’m confused as to why this works. I thought that private methods could not be accessed outside of the class they’re defined in. Could anyone explain why this is possible?
>Solution :
You are not passing a private method.
In fact in Java you can’t pass around methods at all*.
You’re passing around an implementation of Runnable
.
That implementation is created via () -> myPrivateMethod()
. This is a simple way to define some code to implement a functional interface (like Runnable
).
The myPrivateMethod()
here is just a boring old method call. You define some code, that happens to call a private method. Since the method call is allowed in this place, you can create a Runnable
that does this.
The code you showed is roughly equivalent to this:
myService.runRunnable(new Runnable() {
public void run() {
myPrivateMethod();
}
})
which creates an anonymous inner class. While using the lambda expression above doesn’t necessarily create a class, it’s functionally equivalent to this code.
* you might find code that looks like it’s passing around methods, but it’s always just creating implementations of interfaces that call those methods in one way or another.