Perguntas da entrevista sobre o controle de fluxo Java (+ respostas)
1. Introdução
As declarações de fluxo de controle permitem que os desenvolvedores usem a tomada de decisão, o loop e a ramificação para alterar condicionalmente o fluxo de execução de determinados blocos de código.
Neste artigo, examinaremos algumas perguntas da entrevista de controle de fluxo que podem surgir durante uma entrevista e, quando apropriado; vamos implementar exemplos para entender melhor suas respostas.
2. Questões
Q1. Descreva as declaraçõesif-theneif-then-else. Que tipos de expressões podem ser usados como condições?
Ambas as instruções dizem ao nosso programa para executar o código dentro delas somente se uma condição particular for avaliada comotrue. No entanto, a instruçãoif-then-else fornece um caminho secundário de execução no caso de a cláusula if ser avaliada comofalse:
if (age >= 21) {
// ...
} else {
// ...
}
Ao contrário de outras linguagens de programação, Java suporta apenas expressõesboolean como condições. Se tentarmos usar um tipo diferente de expressão, obteremos um erro de compilação.
Q2. Descreva a declaraçãoswitch. Quais tipos de objeto podem ser usados na cláusulaswitch?
O switch permite a seleção de vários caminhos de execução com base no valor de uma variável.
Cada caminho é rotulado comcase oudefault, a instruçãoswitch avalia cada expressãocase para uma correspondência e executa todas as instruções que seguem o rótulo correspondente até umbreakdeclaração s for encontrada. Se não conseguir encontrar uma correspondência, o blocodefault será executado em seu lugar:
switch (yearsOfJavaExperience) {
case 0:
System.out.println("Student");
break;
case 1:
System.out.println("Junior");
break;
case 2:
System.out.println("Middle");
break;
default:
System.out.println("Senior");
}
Podemos usarbyte,short,char,int, suas versões agrupadas,enums eStrings como valoresswitch.
Q3. O que acontece quando nos esquecemos de colocar uma instruçãobreak em uma cláusulacase deswitch?
A instruçãoswitch falha. Isso significa que ele continuará a execução de todos os rótuloscase até encontrar uma instruçãobreak, mesmo que esses rótulos não correspondam ao valor da expressão.
Aqui está um exemplo para demonstrar isso:
int operation = 2;
int number = 10;
switch (operation) {
case 1:
number = number + 10;
break;
case 2:
number = number - 4;
case 3:
number = number / 3;
case 4:
number = number * 10;
break;
}
Depois de executar o código,number mantém o valor 20, em vez de 6. Isso pode ser útil em situações em que queremos associar a mesma ação a vários casos.
Q4. Quando é preferível usar umswitch em vez de uma instruçãoif-then-else e vice-versa?
Uma instruçãoswitch é mais adequada ao testar uma única variável em relação a muitos valores únicos ou quando vários valores executarão o mesmo código:
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
days = 31;
break;
case 2:
days = 28;
break;
default:
days = 30;
}
Uma declaraçãoif-then-else é preferível quando precisamos verificar intervalos de valores ou várias condições:
if (aPassword == null || aPassword.isEmpty()) {
// empty password
} else if (aPassword.length() < 8 || aPassword.equals("12345678")) {
// weak password
} else {
// good password
}
Q5. Que tipos de loops o Java suporta?
Java oferece três tipos diferentes de loops:for,while edo-while.
Um loopfor fornece uma maneira de iterar em uma faixa de valores. É mais útil quando sabemos com antecedência quantas vezes uma tarefa será repetida:
for (int i = 0; i < 10; i++) {
// ...
}
Um loopwhile pode executar um bloco de instruções enquanto uma condição particular étrue:
while (iterator.hasNext()) {
// ...
}
Umdo-while é uma variação de uma instruçãowhile em que a avaliação da expressãoboolean está na parte inferior do loop. Isso garante que o código seja executado pelo menos uma vez:
do {
// ...
} while (choice != -1);
Q6. O que é um loopenhanced for?
É outra sintaxe da instruçãofor projetada para iterar por todos os elementos de uma coleção, matriz, enum ou qualquer objeto que implemente a interfaceIterable:
for (String aString : arrayOfStrings) {
// ...
}
Q7. Como você pode sair antecipadamente de um loop?
Usando a instruçãobreak, podemos encerrar a execução de um loop imediatamente:
for (int i = 0; ; i++) {
if (i > 10) {
break;
}
}
Q8. Qual é a diferença entre uma declaraçãobreak não etiquetada e etiquetada?
Uma instruçãobreak não rotulada termina a instruçãoswitch,for,while oudo-while mais interna, enquanto uma instruçãobreak rotulada termina a execução de uma instrução externa declaração.
Vamos criar um exemplo para demonstrar isso:
int[][] table = { { 1, 2, 3 }, { 25, 37, 49 }, { 55, 68, 93 } };
boolean found = false;
int loopCycles = 0;
outer: for (int[] rows : table) {
for (int row : rows) {
loopCycles++;
if (row == 37) {
found = true;
break outer;
}
}
}
Quando o número 37 é encontrado, a instruçãobreak rotulada termina o loopfor mais externo e nenhum outro ciclo é executado. Assim,loopCycles termina com o valor 5.
No entanto, obreak não rotulado apenas termina a instrução mais interna, retornando o fluxo de controle para ofor mais externo que continua o loop para o próximorow na variáveltable, tornando oloopCycles termina com um valor de 8.
Q9. Qual é a diferença entre uma declaraçãocontinue não etiquetada e etiquetada?
Uma instruçãocontinue não rotulada pula para o final da iteração atual no loop mais internofor,while oudo-while, enquanto umcontinue rotulado pula para um loop externo marcado com o rótulo fornecido.
Aqui está um exemplo que demonstra isso:
int[][] table = { { 1, 15, 3 }, { 25, 15, 49 }, { 15, 68, 93 } };
int loopCycles = 0;
outer: for (int[] rows : table) {
for (int row : rows) {
loopCycles++;
if (row == 15) {
continue outer;
}
}
}
O raciocínio é o mesmo da pergunta anterior. A instruçãocontinue rotulada termina o loopfor mais externo.
Assim,loopCycles termina mantendo o valor 5, enquanto a versão sem rótulo apenas termina a instrução mais interna, fazendo com queloopCycles termine com um valor 9.
Q10. Descreva o fluxo de execução dentro de uma construçãotry-catch-finally.
Quando um programa entra no blocotry, e uma exceção é lançada dentro dele, a execução do blocotry é interrompida, e o fluxo de controle continua com um blococatch que pode lidar com a exceção que está sendo lançada.
Se esse bloco não existir, a execução do método atual será interrompida e a exceção será lançada no método anterior na pilha de chamadas. Alternativamente, se nenhuma exceção ocorrer, todos os blocoscatch são ignorados e a execução do programa continua normalmente.
Um blocofinally sempre é executado se uma exceção foi lançada ou não dentro do corpo do blocotry.
Q11. Em quais situações o blocofinally não pode ser executado?
Quando a JVM é encerrada durante a execução dos blocostry oucatch, por exemplo, chamandoSystem.exit(), ou quando o encadeamento em execução é interrompido ou eliminado, o bloco finally não é executado.
Q12. Qual é o resultado da execução do código a seguir?
public static int assignment() {
int number = 1;
try {
number = 3;
if (true) {
throw new Exception("Test Exception");
}
number = 2;
} catch (Exception ex) {
return number;
} finally {
number = 4;
}
return number;
}
System.out.println(assignment());
O código gera o número 3. Mesmo que o blocofinally sempre seja executado, isso acontece somente após a saída do blocotry.
No exemplo, a instruçãoreturn é executada antes que o blocotry-catch termine. Assim, a atribuição anumber no blocofinally não tem efeito, pois a variável já foi retornada ao código de chamada do métodotestAssignment.
Q13. Em quais situações o blocotry-finally pode ser usado mesmo quando as exceções não podem ser lançadas?
Este bloqueio é útil quando queremos garantir que não ignoramos acidentalmente a limpeza de recursos usados no código, encontrando uma instruçãobreak,continue oureturn:
HeavyProcess heavyProcess = new HeavyProcess();
try {
// ...
return heavyProcess.heavyTask();
} finally {
heavyProcess.doCleanUp();
}
Além disso, podemos enfrentar situações em que não podemos lidar localmente com a exceção que está sendo lançada, ou queremos que o método atual ainda lance a exceção, permitindo-nos liberar recursos:
public void doDangerousTask(Task task) throws ComplicatedException {
try {
// ...
task.gatherResources();
if (task.isComplicated()) {
throw new ComplicatedException("Too difficult");
}
// ...
} finally {
task.freeResources();
}
}
Q14. Comotry-with-resources funciona?
A instruçãotry-with-resources declara e inicializa um ou mais recursos antes de executar o blocotry e os fecha automaticamente no final da instrução, independentemente de o bloco ter sido concluído normalmente ou abruptamente. Qualquer objeto que implemente as interfacesAutoCloseable ouCloseable pode ser usado como um recurso:
try (StringWriter writer = new StringWriter()) {
writer.write("Hello world!");
}
3. Conclusão
Neste artigo, abordamos algumas das perguntas mais frequentes que aparecem em entrevistas técnicas para desenvolvedores Java, sobre declarações de fluxo de controle. Isso deve ser tratado apenas como o início de pesquisas adicionais e não como uma lista exaustiva.
Boa sorte na sua entrevista.