Connect Four game without diagonals check or validation
Magic values

The implementation is mostly fine, except for the widespread magic values that would be better as constants, for example:

private static final char SYMBOL_EMPTY = '□';
private static final char SYMBOL_PLAYER1 = '■';
private static final char SYMBOL_PLAYER2 = '⊠';


Similarly, instead of initializing possiblePositions with new int[] { 5, 5, 5, 5, 5, 5, 5 }, it would be better to derive the correct value from the BOARD_WIDTH and BOARD_HEIGHT constants.

Code duplication

This snippet is duplicated in checkRowAndCol:


if (chainLength == 4) {
    switch (gameBoard[row][col]) {
        case '■':
            gameState = State.PLAYER_1_WIN;
            break;
        case '⊠':
            gameState = State.PLAYER_2_WIN;
            break;
    }
}



It would be better to move this to a helper method.

Unnecessary execution

When a player wins,
you could return immediately from checkRowAndCol,
no need to continue checking all rows and columns.

The helper method I mentioned in the previous section could return a boolean,
with a true value if there is a winner.
When the returned value is true,
the caller in checkRowAndCol could return immediately.

Code organization

Instead of checkRowAndCol, it would be better to separate to checkRow and checkCol methods.
You could still have a checkRowAndCol method that calls the other two,
but there's no reason for these two independent aspects to be implemented in the same method.