Perguntas da entrevista sobre o controle de fluxo Java (+ respostas)

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.