Эти классы зависят друг от друга, т.к. в одном создается экземпляр другого, и наоборот. Само по себе это не страшно, но у Вас это происходит и там, и там прямо в инициализации (то место, где объявляются поля и им тут же присваивается новый экземпляр другого класса).
public class Lois {
Pitter husbend = new Pitter();
...
public class Pitter {
Lois wife = new Lois();
...
Инициализация выполняется всякий раз, когда создается экземпляр этого класса:
... = new Lois();
//or
... = new Pitter();
причем, совершенно неважно, где и почему программа пытается его создавать.
Соответственно, попытка (изначально - где-то в другом месте программы) создать экземпляр любого из этих классов приводит к тому, что для этого сначала потребуется создать новый экземпляр второго, для чего потребуется создать новый экземпляр первого и т.д. до бесконечности. В результате эта самая первая попытка никогда не завершится... точнее, завершится, переполнением стека.
Что такое переполнение стека и почему оно тут происходит? Любое создание объекта (экземпляра класса) "внутри" означает просто-напросто "вызов метода" (статической инициализации, затем конструктора; только после возврата из конструктора объект считается созданным и ссылка на экземпляр может быть чему-то там присвоена). А "вызов метода" означает (немного упрощенно) не что иное, как "положить на стек точку возврата, передаваемые параметры метода и перейти по адресу метода". Метод забирает со стека параметры и точку возврата, в конце кладет на стек свой результат (если он есть), и совершает переход по точке возврата. Если за ней в программе присвоение (как в ваших классах), результат забирается со стека и "присваивается". Таким образом, при нормальном вызове стек остается "чистым". А если вызов уходит в бесконечную цепочку других вызовов, как у Вас, то до очистки дело никогда не доходит, и стек рано или поздно заканчивается. Вот тогда и прилетает StackOverflowError.
Упрощено суть того, что в Вас происходит, можно проиллюстрировать вот так:
public class Main {
public static void main(String[] args) {
// You can run JVM with:
// -XX:MaxJavaStackTraceDepth=-1 (unlimited number of stack trace frames)
// -Xss4m (play around with stack size)
//
try {
first(); // causes stack overflow!
} catch (StackOverflowError e) {
System.err.println("Depth (frames):" + e.getStackTrace().length);
}
}
static int first(){
return second();
}
static int second(){
return first();
}
}
Можете запустить и посмотреть, что будет :)
Чтоб этого не происходило, нужно переделать код, например, вот так:
public class Lois {
Pitter myHusband = new Pitter(this);
public Lois(Pitter whoIsMyHusband){
myHusband = whoIsMyHusband;
}
//...
}
public class Pitter {
Lois myWife = new Lois(this);
public Pitter(Lois whoIsMyWife) {
myWife = whoIsMyWife;
}
// ...
}