O Java não tem uma palavra específica para funções e procedimentos, eles os chamam de métodos, e não existe uma palavra chave que os indiquem (diferente de por exemplo, o PHP, que tem o function, e se retornar valor é uma função, senão é um procedimento).
No caso, para indicar um procedimento em Java, usaremos o void (que é vazio, pra indicar que não terá retorno).
PS: O próprio método principal do Java (public static void main) indica um procedimento.
Esse é o código que colocaremos antes ou depois do void principal, ele deverá ter a indicação de que é um método estático com o static
, tal como o método principal:
static void soma(int a, int b) {
int s = a + b;
System.out.println(s);
}
E pra chamar o procedimento, colocamos apenas isso dentro do método principal:
System.out.println("Começou o programa!");
soma(5, 2);
Observe que o método é executado depois, mesmo com o procedimento ter sido antes, pois por regra, o método main é o primeiro a ser executado.
PS: Os parâmetros não são obrigatórios ter em todas as funções e procedimentos, mas caso tenham, tem que ser passados todos eles nas invocações, e não é possível inicializar esses mesmos parâmetros com valores padrão, o melhor é usar a sobrecarga, que veremos mais pra frente.
Para chamar funções em Java, é de forma parecida com os procedimentos, apenas declarando o tipo primitivo de retorno, no lugar do void (antes ou depois do método principal):
static int soma(int a, int b) {
int s = a + b;
return s;
}
Não esqueça do retorno com a variável dentro do método.
E dentro do método principal, basta apenas fazer isso:
System.out.println("Começou o programa!");
int sm = soma(5, 2);
System.out.println("A soma vale: " + sm);
Nesse caso, o próprio código verá a melhor maneira de exibir, o método do cálculo só se responsabilizou pelo cálculo mesmo, a exibição foi cuidada apenas pelo método principal.
PS: Tem casos que a declaração static não é obrigatória num método. Nos casos acima, é devido ao método main ser estático, e por isso só pode trabalhar com métodos estáticos.
Também podemos fazer sobrecarga de métodos no Java, que é quando temos dois ou mais métodos com o mesmo nome, mas com parâmetros diferentes, por exemplo:
static void saudacao(String nome) {
System.out.println("Olá, " + nome + "!");
}
static void saudacao() {
System.out.println("Olá, visitante!");
}
public static void main(String[] args) {
saudacao("José");
saudacao("Cláudia");
saudacao();
}
Podemos ter várias combinações com métodos de mesmo nome com parâmetros diferentes, como uma com char e outra com int, uma com boolean e outra sem nada, etc., mas os parâmetros precisam ser de combinações de tipos diferentes, independente do tipo de retorno do método.
Agora vamos ver uma iniciação em POO, pra isso vamos criar outro projeto com a classe principal.
Vamos criar uma segunda Classe Java com o nome Operacoes, no mesmo pacote Java (essa não terá o public static void main). Ele automaticamente criará uma classe pública com o nome Operacoes, vamos trabalhar dentro dela.
Dentro da classe pública, criaremos um método no qual vai retornar uma string. Veja o código que vai dentro da classe pública Operacoes:
public static String contador(int ini, int fim) {
String stri = "";
for(int cont = ini; cont <= fim; cont++) {
stri += cont + " ";
}
return stri;
}
Para chamar o método na primeira classe, colocaremos o nome da classe e o método após o ponto, no método principal da primeira. Veja o código:
System.out.println("Vai começar a Contagem!");
System.out.println(Operacoes.contador(1, 5));
PS: No caso acima, o método contador deverá também ser estático, ou dará erro, e de preferência, público. O static permite chamar a função de uma classe sem precisar criar um objeto.
Vamos criar um programa que mostre fatoriais, para isso criaremos, outro programa com classe principal, e nele vamos criar outra classe chamada Fatorial.
Observe que nesse caso, o Fatorial é uma classe de criação de objeto, o que facilitará o código e a formação do programa.
Esse é o código completo da segunda classe, observe que alguns atributos serão privados (encapsulados), nesse caso:
public class Fatorial {
private int num = 0;
private int fat = 1;
private String form = "";
public void setValor(int n) {
num = n;
int f = 1;
String s = "";
for(int cont = n; cont > 1; cont--) {
f *= cont;
s += cont + " x ";
}
s += "1 = ";
fat = f;
form = s;
}
public int getFatorial() {
return fat;
}
public String getFormula() {
return form;
}
}
E na primeira classe, colocamos apenas isso:
Fatorial f = new Fatorial();
f.setValor(5);
System.out.print(f.getFormula());
System.out.println(f.getFatorial());
A classe Fatorial criada nesse programa pode ser reaproveitada em outros projetos, graças à orientação à objetos.
Da mesma forma, faremos um novo programa em Swing.
Para usarmos a classe encapsulada, pegamos a classe Fatorial do primeiro projeto e arrastamos pro pacote java "classes" do segundo projeto (segure o Ctrl pra copiar), clique em refatorar para a classe do segundo projeto.
No frame, colocaremos um objeto giratório, um botão e dois labels para calcular o fatorial. Esse é o código do evento do botão:
int n = Integer.parseInt(numVal.getValue().toString());
Fatorial f = new Fatorial();
f.setValor(n);
lblCont.setText(f.getFormula());
lblFat.setText(Integer.toString(f.getFatorial()));
Essa é a vantagem da orientação à objetos, podemos reaproveitar o código em outros projetos.
PS: Nos parâmetros também podemos passar arrays, passando a variável com colchetes, algo tipo funcao(int vetorpassado[])
.
O try catch finally são utilizados para tratar erros. No bloco try
nós inserirmos a rotina que queremos tratar o provável erro que acontecer. Quando ele acontece o erro no try, para a execução do bloco imediatamente, passa pro catch
e passa essa exceção gerada pra ele, onde o erro será tratado propriamente dito, onde podemos interceptar a exceção e realizar o tratamento mais adequado ao programa. O finally
sempre será executado, ele não é obrigatório.
Esse é a estrutura básica de um try catch:
try {
System.out.println("Mensagem de Teste"); // É executado
}
catch(Exception ex) {
System.err.println("ERRO"); // Não é executado
}
No código acima, apenas o que está no try será executado, já que o código dentro dele está certo, o que está no catch não será executado (o parâmetro dentro dos parênteses do catch pode ser qualquer um).
PS: Podemos usar tanto new Exception quanto new Error. Muitos erros o Java trata automaticamente, mas é preferível tratar para evitar travamentos e melhorar a exibição dos mesmos, e existem outros tratamentos também, como o SQLException
e o NumberFormatException
, esses dois são respectivamente, para tratamento de erros em bancos de dados e de valores não numéricos. Note também que o System.err.println()
imprime em vermelho, por isso é usado pra erros.
Podemos, por exemplo, usar o ArithmeticException
para tratar erros de divisão por zero:
Scanner teclado = new Scanner(System.in, "CP1252"); // Importe
int num1, num2, res;
System.out.print("Digite o dividendo: ");
num1 = teclado.nextInt();
System.out.print("Digite o divisor: ");
num2 = teclado.nextInt();
try {
res = num1 / num2;
System.out.println(res);
}
catch(ArithmeticException ex) {
System.err.println("ERRO: Não é Possível Dividir por Zero!");
}
Podemos também lançar a exceção em uma função, veja um exemplo com a exceção ArithmeticException:
static float divisao(int n1, int n2) {
if(n2 == 0) {
throw new ArithmeticException("É impossível Dividir por Zero!");
}
return n1 / n2;
}
E no método principal:
try {
System.out.println(divisao(50, 0));
}
catch(ArithmeticException ex) {
System.err.println(ex.getMessage());
}
PS: Caso a exceção seja colocada numa função, pode ser necessário colocar throws Exception
(ou equivalente) após a declaração da função, que obrigatoriamente tem que ter um bloco try catch ao ser utilizada.
Como visto acima, podemos também gerar um erro manualmente, veja um exemplo onde uma variável não poderá receber um valor maior do que 10, definido por nós mesmos:
int num;
Scanner teclado = new Scanner(System.in, "CP1252"); // Importe
try {
System.out.print("Digite um valor: ");
num = teclado.nextInt();
if(num > 10) {
throw new Exception("Valor inválido, o valor deverá ser até o máximo de 10!");
}
System.out.println("Valor Digitado: " + num);
}
catch(Exception ex) {
System.err.println("ERRO: " + ex.getMessage());
}
finally {
System.out.println("Fim do tratamento");
}
No caso acima, o que fez criar a exceção, foi o método throw new Exception()
, pode ver que ele nem terminou de executar o código e já pulou pro catch. No finally, ele exibirá a mensagem independente se o erro ocorrer ou não.
Dessa forma, podemos fazer um tratamento melhor pra alguns erros, como o de raiz quadrada:
Scanner teclado = new Scanner(System.in, "CP1252");
int num;
double raiz;
try {
System.out.print("Digite um número para ver a raiz: ");
num = teclado.nextInt();
raiz = Math.sqrt(num);
if(Double.isNaN(raiz)) { // Importe
throw new Exception("Não Existe Raiz Quadrada de Número Negativo!");
}
System.out.println("A raiz quadrada de " + num + " é " + raiz);
}
catch(Exception ex) {
System.err.println("ERRO: " + ex.getMessage());
}
Como exercício, crie um exemplo de tratamento de erros com números com Swing, com um campo de texto e um botão, integrado com JOptionPane, onde ele emite um alerta quando não for inserido um número, esse é o código do evento do botão:
try {
if(txtNum.getText().equals("")) {
throw new Exception("Não foi Inserido Nenhum Dado!");
}
int num = Integer.parseInt(txtNum.getText());
JOptionPane.showMessageDialog(null, "O número digitado é " + num + "\nO dobro dele é " + (num * 2) + "\nO quadrado dele é " + Math.pow(num, 2) + "\nO cubo dele é " + Math.pow(num, 3), "Resultado", JOptionPane.INFORMATION_MESSAGE);
}
catch(NumberFormatException ex) {
JOptionPane.showMessageDialog(null, "Não foi inserido um número válido!\n\n" + ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
}
catch(Exception ex) {
JOptionPane.showMessageDialog(null, ex.getMessage(), "Aviso", JOptionPane.WARNING_MESSAGE);
}
Como visto acima, podemos ter mais de uma exceção catch no mesmo bloco try catch. Um dos Erros foram planejados (o de verificar dados vazios), o de número só é executado ao passarem um caractere não numérico.
Como o Java roda em todos os sistemas operacionais que tenham uma JRE, temos que fazer assim para limpar a tela de console do Java:
Scanner teclado = new Scanner(System.in, "CP1252"); // Importe
System.out.print("Digite algo: ");
String texto = teclado.nextLine();
try {
if(System.getProperty("os.name").contains("Windows")) { // Windows
new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
}
else {
new ProcessBuilder("clear").inheritIO().start().waitFor();
}
}
catch(IOException | InterruptedException ex) { // Importe
System.err.println("ERRO: " + ex.getMessage());
}
System.out.println(texto);
PS: Isso também funciona para outros comandos dos sistemas operacionais especificados, mas os resultados podem não aparecer no console do Netbeans. Como exercício, teste outros comandos desses sistemas.