Por que meu código não está dando certo?

Para responder a seguinte questão:
“Escreva um programa em Java que pe¸ca ao usu´ario para digitar o dia, o mˆes e o ano (iniciando
em 1) de uma data espec´ıfica e valide esta data. Por exemplo, o usu´ario n˜ao pode digitar
dias menores do que zero, mˆes maior que 12 ou um dia 31 para o mˆes de abril. Seu programa
deve considerar anos bissextos.”

Fiz este código:

import java.util.Scanner;

public class Main
{

public static void main(String [] args)
{
    int dia, mes, ano;
    
    Scanner teclado = new Scanner(System.in);
    dia = teclado.nextInt();
    mes = teclado.nextInt();
    ano = teclado.nextInt();
    
   
    
    if(dia <= 30 && mes == 4 || mes == 6 || mes == 9 || mes == 11 && ano <= 2017)
    {System.out.println(dia + "/" + mes + "/" + ano);}
    else if(dia > 30 && mes == 4 || mes == 6 || mes == 9 || mes == 11 && ano > 2017)
    {System.out.println("Esta data não existe!");}
    else if(dia <= 28 && mes == 2 && ano <= 2017)
    {System.out.println(dia + "/" + mes + "/" + ano);}
    else if(dia > 28 && mes == 2 && ano > 2017)
    {System.out.println("Esta data não existe!");}
    else if(dia <= 29 && mes == 2 && ano % 4 == 0 && ano <= 2017) 
    {System.out.println(dia + "/" + mes + "/" + ano);}
    else if(dia > 29 && mes == 2 && ano % 4 != 0 && ano > 2017)
    {System.out.println("Esta data não existe!");}
    else 
    {System.out.println(dia + "/" + mes + "/" + ano);} 
    
        
    }
}

Acontece que o código não responde como eu gostaria, como em situações em que o usuário digita “31 6 2018” em que o programa aceita essa data ao invés de mostrar que esta data é inexistente

O que há de errado?

Você já depurou, seja com prints no console ou com breakpoins?

Aconselho vivamente a NUNCA misturar && e || num mesmo if sem usar parêntesis. A precedência dos operadores é diferente e podes ter resultados diferentes do esperado.

No teu caso, o que pretendes é isto:

if(dia <= 30 && (mes == 4 || mes == 6 || mes == 9 || mes == 11) && ano <= 2017)

mas o que estás a fazer é isto (coloquei parentesis para perceberes):

if((dia <= 30 && mes == 4) || mes == 6 || mes == 9 || (mes == 11 && ano <= 2017))
3 curtidas
int dia, mes, ano;

Scanner teclado = new Scanner(System.in);
System.out.print("Dia: ");
dia = teclado.nextInt();
System.out.print("Mês: ");
mes = teclado.nextInt();
System.out.print("Ano: ");
ano = teclado.nextInt();

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setLenient(false);
String dataString = dia+"/"+mes+"/"+ano;
        
try {
    Date data = sdf.parse(dataString);
    System.out.println("Data: " + sdf.format(data)); 
} catch(ParseException e) {
    System.err.println("Data inválida");
}
if (dia < 1 || dia > 31 || mes < 1 || mes > 12 || ano < 1900 ||
   (dia > 30 && (mes==2||mes==4||mes==6||mes==9||mes==11)) ||
   (mes==2 && dia > 29) ||
   (mes==2 && dia == 29 && (ano%4 != 0 ))) {
    System.err.println("Data inválida");
} else {
    Calendar calendar = new GregorianCalendar(ano,mes-1,dia);
    System.out.println("Data: " + sdf.format(calendar.getTime())); 

No primeiro exemplo usei um método java pra verificar a data. Neste segundo critiquei na mão mesmo. Acho que cobri todas as possibilidades … Enfatizando que restringi o ano que não pode ser inferior a 1900 e verifico se o ano é bissexto “ano%4!=0” para tratar o dia 29 do mês de fevereiro.