This question is more theoretical. So I have this following set of code:
public class Test {
public static void main(String[] args) {
Test test = new Test();
}
{
System.out.println("Instance execution");
}
}
It compiles and prints "Instance Execution". But when I try to execute some other method this way:
public class Test {
public static void main(String[] args) {
Test test = new Test();
}
{
System.out.println("Instance execution");
}
private void anotherMethod() {
System.out.println("Method execution");
}
{
Test test = new Test();
test.anotherMethod();
}
}
It's giving me this error:
Exception in thread "main" java.lang.StackOverflowError
at Test.<init>(Test.java:15)
I'm totally convinced that this error has the easiest explanation, but my question here, is it the constructor that's throwing this error? Or only System methods can be executed this way? This whole approach of executable Instance Initialiser is very new to me, so any help would be much appreciated. Thanks.
The Problem is, that you create a Test obejct in your constructor, which will create another Test object and so on. Instead use
this.anotherMethod();
This:
{
Test test = new Test();
test.anotherMethod();
}
is an instance initializer block. It runs every time you create a Test
instance. Within it, you're...creating a new Test
instance, which naturally triggers the block, which then creates a new Test
instance, which triggers the block... You get the idea.
is it the constructor that's throwing this error?
It's instance initialization, yes. And in fact, under the covers, the way instance initializer blocks are handled by the compiler is to literally copy that code into the beginning of every constructor in the class (including the default one, if you don't supply a default one), just after any call to super
(the default one if there isn't an explicit one). So you could say it's the constructor throwing the error, even if conceptually, it's instance initialization as distinct from the constructor per se.
Or only System methods can be executed this way?
Not sure what you mean by "System methods," but the issue is that the initializer block is run per-instance. If you wanted it run only once, at class initialization time, you could use a static
initializer block:
public class Test {
public static void main(String[] args) {
Test test = new Test();
}
{
System.out.println("Instance execution");
}
private void anotherMethod() {
System.out.println("Method execution");
}
static // <==================
{
System.out.println("Class initialization"); // ***
Test test = new Test();
test.anotherMethod();
}
}
That outputs:
Class initialization Instance execution Method execution Instance execution
(We see "Instance execution" twice because there's one new Test
in main
, and another in the static
initializer block.)
But really, the simplest thing is to put the call to anotherMethod
in main
:
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.anotherMethod();
}
{
System.out.println("Instance execution");
}
private void anotherMethod() {
System.out.println("Method execution");
}
}
which outputs
Instance execution Method execution
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With