Introdução
Como sabemos, Java é uma linguagem de programação orientada a objetos. Ou seja, o conceito básico, porque dizer que a base dos fundamentos é que tudo é um objeto. Os objetos são descritos usando classes.
As classes, por sua vez, possuem estado e comportamento. Por exemplo, uma conta bancária pode ter um estado na forma da quantidade de dinheiro na conta e ter o comportamento de aumentar e diminuir o saldo. O comportamento em Java é implementado usando métodos. Como descrever métodos é apresentado logo no início de sua jornada de aprendizado Java. Por exemplo, no tutorial oficial da Oracle: “
Definindo Métodos ”. Existem dois aspectos importantes aqui:
- Cada método possui uma assinatura. A assinatura consiste no nome do método e seus parâmetros de entrada;
- Os métodos devem especificar um tipo de retorno;
- O tipo de retorno não faz parte da assinatura do método.
Novamente, isso é uma consequência do fato de que Java é uma linguagem fortemente tipada e o compilador deseja entender antecipadamente quais tipos são usados, tanto quanto possível. Novamente, para nos proteger de erros. Em geral, tudo é para o bem. Bem, isso mais uma vez incute em nós uma cultura de manipulação de dados, me parece. Portanto, para métodos, o tipo de valor é especificado. E para retornar esse mesmo valor dos métodos, utiliza-se a palavra-chave
return
.
Instrução de retorno de palavra-chave em Java
A palavra-chave declaração
return
refere-se a "declarações de fluxo de controle", conforme discutido no tutorial do Oracle "
Declarações de fluxo de controle ". Você também pode ler sobre como retornar valores no tutorial oficial: “
Retornando um valor de um método ”. O compilador monitora cuidadosamente, da melhor maneira possível, se o valor retornado de um método corresponde ao tipo de valor de retorno especificado pelo método.
Vamos usar o IDE online do tutorialspoint como exemplo . Vejamos o exemplo original:
public class HelloWorld {
public static void main(String []args) {
System.out.println("Hello World");
}
}
Como podemos ver, aqui é executado um método
main
, que é o ponto de entrada do programa. As linhas de código são executadas de cima para baixo. Nosso
main
método não pode retornar valores, caso contrário receberemos um erro: "
Error: Main method must return a value of type void
". Portanto, o método simplesmente será exibido na tela. Vamos agora mover o recebimento da string para um método separado para receber a mensagem:
public class HelloWorld {
public static void main(String []args) {
System.out.println(getHelloMessage());
}
public static String getHelloMessage() {
return "Hello World";
}
}
Como podemos ver, usando a palavra-chave
return
especificamos o valor de retorno, que usamos posteriormente no método
println
. Na descrição (definição) do método
getHelloMessage
indicamos que ele nos retornará
String
. Isso permite que o compilador verifique se as ações do método são consistentes com a forma como ele é declarado. Naturalmente, o tipo do valor de retorno especificado na definição do método pode ser mais amplo do que o tipo do valor retornado do código, ou seja, O principal é que os tipos se reduzem uns aos outros. Caso contrário, obteremos um erro de tempo de compilação: "
error: incompatible types
". A propósito, a questão provavelmente surgiu imediatamente: Por que
return
isso se aplica aos operadores de controle de fluxo de programas? Mas porque pode atrapalhar o fluxo normal do programa de cima para baixo. Por exemplo:
public class HelloWorld {
public static void main(String []args){
if (args.length == 0) {
return;
}
for (String arg : args) {
System.out.println(arg);
}
}
}
Como pode ser visto no exemplo, interrompemos a execução do método
main
se nosso programa java for chamado sem parâmetros. É importante lembrar que se você
return
tiver o código, ele ficará inacessível. E nosso compilador inteligente perceberá isso e não permitirá que você execute tal programa. Por exemplo, este código não irá compilar:
public static void main(String []args) {
System.out.println("1");
return;
System.out.println("2");
}
Existe um truque sujo para contornar isso. Por exemplo, para fins de depuração ou por algum outro motivo. O código acima pode ser corrigido envolvendo-o
return
em
if
um bloco:
if (2==2) {
return;
}
Instrução de retorno no tratamento de erros
Há uma circunstância muito complicada: podemos usá-la
return
em conjunto com o tratamento de erros. Gostaria de dizer desde já que usá-lo
return
em
catch
um bloco é muito, muito ruim, então você deve evitá-lo. Mas precisamos de um exemplo, certo? Aqui está ele:
public class HelloWorld {
public static void main(String []args) {
System.out.println("Value is: " + getIntValue());
}
public static int getIntValue() {
int value = 1;
try {
System.out.println("Something terrible happens");
throw new Exception();
} catch (Exception e) {
System.out.println("Catched value: " + value);
return value;
} finally {
value++;
System.out.println("New value: " + value);
}
}
}
À primeira vista parece que 2 deveria ser retornado, pois
finally
é sempre executado. Mas não, o valor será 1 e a alteração na variável
finally
será ignorada. Além disso, se
value
contivesse um objeto e disséssemos
finally
,
value = null
ele
catch
ainda retornaria uma referência ao objeto, não
null
. Mas a partir do bloco
finally
o operador
return
teria funcionado corretamente. Os colegas claramente não agradecerão por tal presente.
void.class
E finalmente. Você pode escrever uma construção estranha como
void.class
. Ao que parece, por que e qual é o objetivo? Na verdade, em vários frameworks e casos complicados onde
a API Java Reflection é usada , isso pode ser muito necessário. Por exemplo, você pode verificar que tipo um método retorna:
import java.lang.reflect.Method;
public class HelloWorld {
public void getVoidValue() {
}
public static void main(String[] args) {
for (Method method : HelloWorld.class.getDeclaredMethods()) {
System.out.println(method.getReturnType() == void.class);
}
}
}
Isto pode ser útil em frameworks de teste onde é necessário substituir o código real dos métodos. Mas para fazer isso, você precisa entender como esse método se comporta (ou seja, quais tipos ele retorna). Existe uma segunda maneira de implementar o método
main
do código acima:
public static void main (String[] args) {
for (Method method : HelloWorld.class.getDeclaredMethods()) {
System.out.println(method.getReturnType() == Void.TYPE);
}
}
Uma discussão bastante interessante sobre a diferença entre eles pode ser lida no stackoverflow:
Qual é a diferença entre java.lang.Void e void? #Viacheslav
GO TO FULL VERSION