0

I am trying to make a list of new objects within that object's class using Arrays.asList(), but for some reason I cannot understand why is that. Can someone explain me the reason ? There is no issue when the method is called to get a list in main, but there is something with it.(Here is the code and error message I get):`

public class Poacher extends Enemy {

    private final List<Poacher> poacherForBattleLvl1 = Arrays.asList(
            new Poacher("PoacherLvl1.1", 10, 1, 4),
            new Poacher("PoacherLvl1.2", 11, 1, 5),
            new Poacher("PoacherLvl1.3", 12, 1, 6),
            new Poacher("PoacherLvl1.4", 14, 1, 12),
            new Poacher("PoacherLvl1.5", 15, 1, 13)
    );

    private Poacher(String name, int health, int level, int gold) { }

    public List<Poacher> getPoachersByLevel(int level) {
        return switch (level) {
            case 1 -> this.poacherForBattleLvl1;
            case 2 -> this.poacherForBattleLvl2;
            case 3 -> this.poacherForBattleLvl3;
            default -> null;
        };
    }
}

Error message:

Exception in thread "main" java.lang.StackOverflowError
at gazi.university.Enemy_SubClasses.Poacher.<init>(Poacher.java:11)
at gazi.university.Enemy_SubClasses.Poacher.<init>(Poacher.java:11)
at gazi.university.Enemy_SubClasses.Poacher.<init>(Poacher.java:11)
at gazi.university.Enemy_SubClasses.Poacher.<init>(Poacher.java:11)
at gazi.university.Enemy_SubClasses.Poacher.<init>(Poacher.java:11)
at gazi.university.Enemy_SubClasses.Poacher.<init>(Poacher.java:11)
at gazi.university.Enemy_SubClasses.Poacher.<init>(Poacher.java:11)
at gazi.university.Enemy_SubClasses.Poacher.<init>(Poacher.java:11)
at gazi.university.Enemy_SubClasses.Poacher.<init>(Poacher.java:11)
....
MC Emperor
  • 22,334
  • 15
  • 80
  • 130
Rahman
  • 15
  • 7
  • 6
    Every Poacher object you create will create another 5 Poachers for your poacherForBattleLvl1 List, which each then will again create 5 Poacher Objects each etc pp. until all your memory is full with Poachers. Either don't declare and intialize your `List poacherForBattleLvl1` inside the Poacher class itself, or make it static so that it only exists once and not once for every Poacher object. – OH GOD SPIDERS Jan 04 '22 at 10:39
  • Hi. I'm supprised that this even compiles, since variables poacherForBattleLvl2 and poacherForBattleLvl3 are not declared. Anyway, stackoverflow error usually means too deep recursion (https://stackoverflow.com/questions/214741/what-is-a-stackoverflowerror). Please give us more complete code... Ah I see now. If you call new Poacher() it creates array of Poachers calling Poacher constructor N-times creating array of Poachers calling the constructor N-times and so on... – Klemikaze Jan 04 '22 at 10:40
  • @OHGODSPIDERS thanks a lot, your solution helped me to solve that problem. – Rahman Jan 04 '22 at 11:50
  • @Klemikaze thanks for explanation; now, I will keep in mind that since now on. – Rahman Jan 04 '22 at 11:51
  • Reviewer comment (and advice): When you create a question, it is recommended to avoid general wording in question header, but to be as specific as possible (so that people looking just at the header could identify the area of the question). In your case, it would be nice to mention the "StackOverflowError" in the header. Another nice feature is question tagging. By adding a tag like [java] you can mark which technology your question applies to. – manuna Jan 11 '22 at 12:49
  • 1
    @manuna Thanks for advice. I rarely ask any questions in stackoverflow, that's why my question seems not specific. I will keep your advice in mind next time. – Rahman Jan 15 '22 at 09:30
  • 1
    @manuna Adding tags to titles is not appropriate, that is what the tagging system is for. – Mark Rotteveel Jan 23 '22 at 17:23
  • @MarkRotteveel that's right. Sorry, I didn't think about user being able to put a tag not using the tagging system, like adding it to the title as you said. – manuna Jan 24 '22 at 15:52

1 Answers1

1

As commented, you have an infinite recursion problem. Each time you instantiate a poacher, you populate a new list with new poachers, each of which creates a new list of poachers each of which creates a list of new poachers each of which creates a new list of poachers … and so on, without end.

As mentioned in the comment, one immediate solution is to mark the list as static. This means there will be only one instance of the list no matter how many times the class constructor is invoked by new Poacher calls.

The optimal solution is to rethink your design. And learn about separation of concerns.

The Poacher class should focus on one thing: What it takes to be a poacher in good working order. Data validation of its inputs is one of its main tasks.

That class should not know about gathering poachers together on a collection. Nor should that class know about configuring levels.

class Poacher {
    String name ;
    int health, level, gold ;

    // Constructor
    private Poacher( final String name, final int health, final int level, final int gold ){
        // Validate inputs. 
        Objects.requireNonNull( name ) ;
        boolean validName = ( ! name.isBlank() ) ;
        if ( ! validName ) { throw new IllegalArgumentException ( … ) ; }
        boolean validHealth = ( health > 0 ) && ( health < 100 ) ;
        if ( ! validHealth ) { throw new IllegalArgumentException ( … ) ; }
        … ditto for other arguments. 

        // Assign inputs. 
        this.name = name ;
        … ditto for other arguments. 
    }
}

I am guessing that a better design is to define a Level class. That class carries a member field for a collection of Poacher objects.

class Level {
    final int levelNumber ;
    List< Poacher > poachers ; 

    …
} 

You create another class to represent the game’s content. In that Game class is where you define each level and its assigned group of poachers.

class Game {
    final List< Level > levels ; 

    …
} 

You define yet another class called something like Application or Main that handles the lifecycle of your game app. It’s tasks include reading in stored state of a suspended game, and writing out the state to storage when game suspends. The main goal of this class is configuring the Game object, and starting gameplay.

The application object creates a game object. The game object creates a set of level objects. Each level object creates a set of poachers objects. Voilà, no more infinite recursion.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154