Bom dia.
O throws é usado para disparar uma exception, enquanto o try/catch é usado para tratar uma exception.
Quando colocamos o throw na assinatura estamos falando que sabemos que nosso código pode gerar uma exception mas naquele momento não estamos interessados em tratar ela e quem for usar o nosso método será responsável de fazer o tratamento.
Para Exceções, são 3 opções:
1 - try/catch: uso quando não quero que a exceção se perpetue pelo código, pois não vou usar aquele "problema" em nenhum outro lugar.
2 - throws: quando quero passar a possível exceção do método que estou para outras classes, quando o tratamento não é necessário naquela classe pois vou precisar da exceção em outra classe.
3 - throw: quando eu quero lançar uma exceção/quando quero que aquele método especifico de um erro(exceção)
Um exemplo prático
Digamos que você tenha um método bla() que precisa do valor da divisão entre dois valores. Para isso, você chama o método divide().
public void bla() {
int a;
int b;
double resposta = divide(a,b);
...
}
Sabemos que não existe divisão por 0 e que pode dar erro, então disparamos uma IllegalArgumentException no método divide() para alertar caso ocorra esta situação. Neste caso, usamos o throw
public double divide(int numerador, int denominador) throws IllegalArgumentException {
if(denominador==0) {
throw new IllegalArgumentException("divisão por 0");
}
return numerador/denominador;
}
Do jeito que está, o método bla() vai compilar normalmente. Se o método divide() disparar uma exception, o bla() vai "quebrar", ou seja, vai parar a execução pois ele não saberá o que fazer com a exception. Para que o código não quebre e pare no meio, é preciso tratar essa exception e para isso usamos o try/catch.
Logo, nosso bla() ficaria assim:
public void bla() {
int a;
int b;
double resposta;
try {
resposta = divide(a,b);
} catch (IllegalArgumentException e) {
System.out.println("Quebrou");
}
...
}
Neste caso, o código não vai quebrar. O método bla() está tratando um possível erro e alterando o fluxo da compilação.