Здравствуйте более опытные, и не очень, товарищи-джависты! Есть часть кода
import java.util.ArrayList;
import java.util.Scanner;

public class Solution {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Input the carrying capacity of the backpack: ");
        int carrying = scanner.nextInt();
        System.out.print("Input the number of items to generate: ");
        int nThings = scanner.nextInt();

        ArrayList<Thing> thingsList = new ArrayList<>();
        for (int i = 0; i < nThings; i++) {
            thingsList.add(new Thing(carrying));
        }

        System.out.println("generated " + nThings + " things with the following characteristics:");

        for (Thing th : thingsList
        ) {
            System.out.println("Thing with a weight of " + th.weight + " and a coast of " + th.cost);
        }

        scanner.close();
    }

    public static class Thing {
        private int weight;
        private int cost;

        public int getWeight() {
            return weight;
        }

        public int getCost() {
            return cost;
        }

        public Thing(int carrying) {
            this.cost = (int) ((Math.random() * 999) + 1);                 //The minimum coast is 1
            this.weight = (int) ((Math.random() * (carrying - 1)) + 1);    //The minimum weight is 1
        }
    }
}
интересует, почему при выставленных модификаторах private
private int weight;
private int cost;
доступ к полям осуществляется без геттеров
for (Thing th : thingsList
        ) {
            System.out.println("Thing with a weight of " + th.weight + " and a coast of " + th.cost);
        }
Также буду очень признателен за любые конструктивные замечания по коду! P.S. пытаюсь решить интересную задачку про Рюкзак, а код - обвес к решению