Métodos Java e decomposição de programas

Aprenda a escrever seus próprios métodos estáticos em Java e a construir programas com eles. Defina e chame métodos, passe informações por parâmetros e receba resultados com return. Descubra onde cada variável pode ser usada, por que um método trabalha com cópias dos valores de seus argumentos e como a pilha de chamadas acompanha os métodos em execução. Faça sobrecarga de métodos e preveja qual versão Java chama. Por fim, divida um problema em pequenos métodos que fazem uma tarefa cada, elimine código repetido e construa e teste um programa um método de cada vez.

BásicoAula 3 de 11 do curso Curso de Programação orientada a objetos com Java

O que você vai aprender

  1. Defina métodos estáticos, chame-os a partir de main e de outros métodos e forneça as informações necessárias por meio de parâmetros.
    • Defina um método e chame-o
      Escreva o cabeçalho e o corpo de um método no lugar correto, chame o método pelo nome e acompanhe como a execução passa para o método e retorna.
    • Passe informações para um método por meio de parâmetros
      Declare parâmetros com tipo e nome, chame o método com argumentos compatíveis e use vários parâmetros na ordem correta.
  2. Escreva métodos que calculam um valor e o devolvem com return e use os valores retornados em variáveis, expressões e condições.
    • Retorne um valor e use-o
      Declare um tipo de retorno, devolva um resultado com uma instrução return e decida no código que chama o método o que acontece com o valor retornado.
    • Retorne de dentro de estruturas condicionais e laços
      Use instruções return dentro de instruções if e laços, garanta que todos os caminhos retornem um valor e escreva métodos que respondam a uma pergunta de sim ou não.
  3. Saiba onde cada variável pode ser usada, o que um método pode ou não alterar no código que o chama e como a pilha de chamadas acompanha os métodos em execução.
    • Identifique onde cada variável pode ser usada
      Aplique as regras de escopo para variáveis locais, parâmetros e variáveis declaradas em blocos e corrija os erros de compilação causados por problemas de escopo.
    • Compreenda que os valores dos argumentos são passados como cópias
      Preveja o que um método pode alterar no código que o chama: o método trabalha com cópias dos valores dos argumentos, portanto reatribuir um parâmetro não altera a variável de quem chamou.
    • Acompanhe as chamadas de métodos na pilha de chamadas
      Acompanhe como Java registra métodos em execução em registros de ativação, rastreie programas em que métodos chamam outros métodos e interprete um rastreamento da pilha.
  4. Dê o mesmo nome a vários métodos com listas de parâmetros diferentes e preveja qual versão Java chama para um conjunto de argumentos.
    • Escreva métodos sobrecarregados
      Declare métodos que compartilham um nome, saiba quais diferenças tornam uma sobrecarga válida e use sobrecarga quando os métodos realizam a mesma tarefa.
    • Preveja qual método sobrecarregado será executado
      Determine qual versão Java escolhe a partir dos tipos dos argumentos, incluindo a conversão automática de ampliação, e reconheça chamadas que não compilam.
  5. Divida um problema em pequenos métodos que fazem uma tarefa cada, substitua código repetido por métodos parametrizados e construa e teste um programa um método de cada vez.
    • Atribua uma tarefa clara a cada método
      Reconheça um programa bem dividido, separe código que faz tarefas demais e mantenha o cálculo separado da entrada e da saída.
    • Substitua código repetido por um método parametrizado
      Encontre código repetido com pequenas diferenças, transforme-o em um método cujos parâmetros representem essas diferenças e verifique se o programa continua se comportando da mesma forma.
    • Projete um programa de forma descendente e teste cada método
      Planeje um programa como uma sequência de chamadas de métodos, escreva-o passo a passo com métodos provisórios e teste cada método com entradas cujos resultados você conhece.

Guia de estudo de Métodos em Java

5 capítulos

1

Escreva e chame seus próprios métodos

Um programa fica mais fácil de acompanhar quando suas etapas significativas têm nomes. Um método dá um nome a um grupo de instruções, e uma chamada executa essas instruções no ponto em que são necessárias. Comece com um método que sempre exibe a mesma linha e depois adicione parâmetros para que uma definição possa lidar com entradas diferentes. Ler um cabeçalho e relacioná-lo a uma chamada permite ver quais informações cada etapa precisa antes de examinar seu corpo.

1.1 Defina um método e chame-o

Um método é um bloco nomeado de instruções que executa uma tarefa. Definir um método disponibiliza essa tarefa; chamá-lo faz a tarefa ser executada.

Leia o cabeçalho e o corpo
public static void printLine() {
    System.out.println("----------");
}

A primeira linha é o cabeçalho. Leia suas partes da esquerda para a direita:

  • public permite que código de outras classes chame o método.
  • static faz o método pertencer à classe. Não é necessário um objeto para chamá-lo.
  • void indica que o método não retorna valor.
  • printLine nomeia a tarefa.
  • () é a lista de parâmetros vazia: este método não precisa de entrada.

As chaves delimitam o corpo, as instruções executadas em uma chamada. Não há ponto e vírgula entre esse cabeçalho e sua chave de abertura.

Coloque a definição na classe
public class Main {
    public static void main(String[] args) {
        System.out.println("Start");
        printLine();
        System.out.println("Middle");
        printLine();
    }

    public static void printLine() {
        System.out.println("----------");
    }
}

main e printLine são métodos separados dentro de Main. A chave de fechamento de main vem antes da definição de printLine. Um método não pode ser definido dentro de outro; uma chave fora do lugar pode produzir “illegal start of expression”.

As definições podem aparecer em qualquer ordem. Mover printLine para cima de main não altera o momento em que ele é executado. Um método que nunca é chamado não é executado apenas porque sua definição aparece no arquivo.

Acompanhe uma chamada e o retorno a quem chamou

A chamada printLine(); consiste no nome, nos parênteses e em um ponto e vírgula, pois a chamada é uma instrução isolada. A execução começa em main:

  1. Exibe “Start”.
  2. Entra em printLine, exibe dez hífens e continua após a chamada.
  3. Exibe “Middle”.
  4. Entra novamente em printLine e exibe dez hífens outra vez.

A saída é:

Start
----------
Middle
----------

As duas chamadas usam a mesma definição. Alterar a linha que ela exibe muda os dois lugares que a usam.

Nomeie e chame métodos com precisão

Use um verbo ou expressão verbal em camelCase, começando com letra minúscula: printReceipt, calculateAverage ou isValidCode. Java trata maiúsculas e minúsculas como diferentes: PrintLine() não encontra um método chamado printLine. Escrever printLine; também falha; os parênteses fazem parte da chamada.

Para um método estático de outra classe, escreva primeiro o nome da classe. Math.max(3, 8) resulta em 8, Math.abs(-4) resulta em 4 e Math.sqrt(16.0) resulta em 4.0. Seus próprios métodos na mesma classe podem ser chamados apenas pelo nome.

Estes exemplos usam a forma clássica baseada em classe com public static void main(String[] args). O Java 25 também aceita arquivos-fonte compactos com void main() e sem uma classe envolvendo o código. Mantenha a forma clássica ao executar estes exemplos; seus métodos auxiliares são declarados static. Métodos da biblioteca de Java que você chama, como System.out.println, não precisam ser estáticos.

Principais conclusões

  • Coloque as definições de métodos dentro da classe e fora de outros métodos.
  • Uma definição disponibiliza uma tarefa; uma chamada a executa e depois continua em quem chamou.
  • Escreva parênteses em uma chamada e ponto e vírgula quando a chamada for uma instrução.
  • Use um nome descritivo em camelCase e respeite exatamente as letras maiúsculas e minúsculas.
  • Chame um método estático de outra classe com o nome da classe, como em Math.max(3, 8).

1.2 Passe informações para um método por meio de parâmetros

Um parâmetro permite que um método lide com valores que mudam de uma chamada para outra. Um argumento é o valor fornecido para esse parâmetro quando o método é chamado.

Dê um tipo e um nome a cada entrada
public static void printStars(int count) {
    for (int i = 0; i < count; i++) {
        System.out.print("*");
    }
    System.out.println();
}

int count declara um parâmetro. Em printStars(3);, o argumento 3 se torna o valor inicial de count. O laço é executado três vezes, portanto exibe *** e println() encerra a linha. printStars(8); usa o mesmo corpo com count igual a 8.

O tipo é escrito na definição, não na chamada. Escreva printStars(5);, não printStars(int 5);.

Avalie os argumentos antes de entrar no corpo

Um argumento pode ser um literal, uma variável ou uma expressão:

int n = 4;
printStars(n * 2);

Java avalia n * 2 primeiro. Ele passa o valor resultante 8, portanto o corpo começa com count igual a 8. O nome da variável de quem chama não precisa ser igual ao nome do parâmetro.

Associe vários parâmetros por posição

Cada parâmetro precisa de seu próprio tipo. Um método para desenhar retângulos pode começar com este cabeçalho:

public static void printRectangle(int width, int height)

A chamada printRectangle(5, 2); atribui a width o valor 5 e a height o valor 2. Inverter os argumentos produz um retângulo com 2 de largura e 5 de altura. Ambas as chamadas compilam porque os dois argumentos são int; apenas a forma desejada indica qual ordem está correta. Escrever (int width, height) no cabeçalho falha porque height não tem tipo declarado.

Tipos diferentes tornam alguns erros de ordem mais fáceis de identificar:

public static void printRepeated(String text, int times) {
    for (int i = 0; i < times; i++) {
        System.out.print(text);
    }
    System.out.println();
}

printRepeated("ab", 3); exibe “ababab”. printRepeated(3, "ab"); não corresponde a uma String seguida de um int. A quantidade de argumentos também deve corresponder: printRectangle(5); deixa um parâmetro sem valor.

Verifique tipos numéricos compatíveis

Java converte automaticamente um int em double por ampliação. Um método com parâmetros (double km, double hours) aceita os argumentos (150, 2), recebendo 150.0 e 2.0. Todo valor int pode ser representado exatamente como double.

Java não converte implicitamente um argumento double para um parâmetro int por estreitamento. printStars(2.9); falha porque a conversão perderia a parte fracionária. A conversão explícita em printStars((int) 2.9); produz 2, portanto dois asteriscos são exibidos. Use uma conversão explícita apenas quando descartar essa parte for o comportamento desejado.

Escolha um parâmetro para cada informação necessária à tarefa. Receber um texto e uma contagem permite usar printRepeated com entrada do teclado, uma chamada de teste fixa ou outro método. Seu corpo não precisa decidir de onde vieram esses valores.

Principais conclusões

  • Um parâmetro é declarado em um cabeçalho; um argumento fornece seu valor em uma chamada.
  • Java avalia as expressões dos argumentos antes de executar o método chamado.
  • Os argumentos correspondem aos parâmetros por posição, quantidade e tipo compatível.
  • Escreva um tipo para cada parâmetro, mas nenhum tipo na chamada.
  • Um int pode ser ampliado para double; um double precisa de conversão explícita para se tornar int.
  • Trocar argumentos do mesmo tipo pode compilar e ainda assim alterar o resultado.
2

Retorne resultados de métodos

Um método pode fazer mais do que exibir: ele pode devolver um valor ao código que o chamou. Isso permite usar um cálculo em outro cálculo, em uma condição ou em um relatório posterior. Acompanhe como tipos de retorno, expressões e atribuições se relacionam e depois use retornos em decisões e buscas. A posição de um return importa: ela determina tanto a resposta que chega a quem chamou quanto a parte do método que tem chance de ser executada.

2.1 Retorne um valor e use-o

Um valor de retorno é um resultado enviado por um método a quem o chamou. Depois que uma chamada termina, ela pode ser usada como uma expressão com o tipo desse resultado.

Declare o que é devolvido
public static int sum(int a, int b) {
    return a + b;
}

int substitui void no cabeçalho porque esse método devolve um inteiro. A instrução return avalia a + b e envia o valor ao ponto da chamada. Para sum(4, 7), esse valor é 11.

Quem chama decide o que acontece em seguida:

int total = sum(4, 7);
System.out.println(sum(4, 7));
int doubled = sum(2, 3) * 2;

A primeira linha armazena 11; a segunda exibe 11; a terceira armazena 10. Um valor retornado também pode ser usado em uma condição, como if (sum(a, b) > 10).

Um resultado int compatível pode ser ampliado ao ser retornado por um método double. Um resultado double não pode ser retornado por um método int sem uma conversão explícita adequada.

Calcule a expressão antes de converter o resultado
public static double average(int a, int b) {
    return (a + b) / 2.0;
}

Para average(3, 4), o numerador é 7. Dividir pelo literal double 2.0 resulta em 3.5. Se a expressão fosse (a + b) / 2, Java primeiro dividiria dois valores int e obteria 3. Só então ampliaria esse valor para o 3.0 retornado. Um tipo de retorno double não corrige uma divisão inteira já realizada dentro do corpo.

Distinga retornar de exibir
Comportamento do métodoO que quem chama recebeO que aparece na tela
return a + b; em um método intA somaNada dessa instrução
System.out.println(a + b); em um método voidNenhum valorA soma

Uma chamada void não pode fornecer um valor em uma atribuição ou outra chamada. Se printSum for void, int total = printSum(1, 2); falha mesmo que printSum exiba um número. Use um método que retorna valor para cálculos e deixe que quem chama escolha se vai exibi-lo.

Retorne texto e respostas de sim ou não

Os tipos de retorno também incluem String e boolean. Um método de saudação pode retornar "Hello, " + name + "!", resultando em “Hello, Ana!” para o argumento "Ana". Um método isEven(int n) pode retornar n % 2 == 0.

Um método de formatação transforma um número em texto reutilizável:

public static String formatDuration(int minutes) {
    return minutes / 60 + " h " + minutes % 60 + " min";
}

Para 135, a divisão inteira resulta em 2 horas inteiras e o resto resulta em 15 minutos. O resultado é “2 h 15 min”; para 60, é “1 h 0 min”.

Guarde ou combine o resultado

Uma chamada como sum(4, 7); compila, mas descarta seu resultado. Se square(x) retornar um novo valor, use x = square(x); para armazená-lo em x.

Um resultado também pode se tornar um argumento imediatamente. Em Math.max(sum(1, 2), 4), sum(1, 2) primeiro resulta em 3 e depois Math.max(3, 4) resulta em 4. Avalie a chamada interna antes de usar seu resultado na chamada externa.

Principais conclusões

  • O tipo de retorno declarado informa a quem chama que tipo de resultado a chamada fornece.
  • Retornar fornece um valor; exibir mostra um valor.
  • A expressão é calculada antes de seu resultado ser convertido para o tipo de retorno.
  • Armazene um valor retornado quando o código posterior precisar dele; uma chamada isolada o descarta.
  • Um valor retornado pode ser argumento de outro método.

2.2 Retorne de dentro de estruturas condicionais e laços

Uma instrução return encerra imediatamente a chamada do método atual. Dentro de uma condição ou de um laço, ela ainda encerra o método inteiro, não apenas aquele bloco.

Dê uma resposta a cada caminho
public static int larger(int a, int b) {
    if (a > b) {
        return a;
    }
    return b;
}

larger(9, 4) retorna 9 de dentro do if. Para larger(2, 6), o corpo do if é ignorado e o return final fornece 6. Entradas iguais como (5, 5) também chegam ao return final, que fornece 5. Não é necessário else após o primeiro return porque esse caminho já saiu do método.

Em um método comum que retorna valor, nenhum caminho possível pode chegar à chave de fechamento sem fornecer um valor. Um método de sinal que retorna apenas para entradas positivas e negativas deixa o zero sem resposta:

public static String sign(int n) {
    if (n > 0) {
        return "positive";
    } else if (n < 0) {
        return "negative";
    }
    return "zero";
}

O return final completa o método. Duas instruções if separadas, uma testando n > 0 e outra testando n <= 0, ainda precisam de um return final ou de uma estrutura if/else clara. A verificação de retorno de Java não deduz que essas duas comparações abrangem todos os inteiros. Uma instrução diretamente após um return incondicional no mesmo bloco é inalcançável e rejeitada.

Termine uma busca no momento certo
public static int firstMultipleOf7(int start, int end) {
    for (int i = start; i <= end; i++) {
        if (i % 7 == 0) {
            return i;
        }
    }
    return -1;
}

Para (10, 20), o laço rejeita 10, 11, 12 e 13 e retorna 14. A chamada termina sem verificar de 15 a 20. Para (15, 20), o laço termina sem encontrar correspondência, portanto o return depois dele fornece -1, o sinal combinado de “não encontrado”.

Colocar else { return -1; } dentro do laço encerraria a busca após o primeiro candidato rejeitado. A busca a partir de 10 informaria falha antes de chegar a 14. O retorno de falha deve vir após a verificação de todos os candidatos.

Retorne a própria condição

Uma comparação já produz um booleano. Escreva return n % 2 == 0; em vez de um if/else que retorna true e false separadamente. O nome de um método com retorno booleano geralmente começa com is ou has, de modo que uma chamada possa ser lida naturalmente dentro de um if.

public static boolean isLeapYear(int year) {
    return (year % 4 == 0 && year % 100 != 0)
        || year % 400 == 0;
}

Isso retorna true para 2024 e 2000, mas false para 1900 e 2023. Use if (isLeapYear(y)) diretamente.

Saia antecipadamente de um método void

Um método void usa return; sem valor. Por exemplo, printSquareRoot(double x) pode exibir “No real square root” e retornar imediatamente para uma entrada negativa. Para outras entradas, pode exibir Math.sqrt(x), que resulta em 1.5 para 2.25. Escrever return 5; em um método void falha porque seu cabeçalho promete não retornar valor.

Principais conclusões

  • return encerra imediatamente a chamada atual, inclusive quando está dentro de um laço.
  • Um método que retorna valor não deve chegar à chave de fechamento sem uma resposta.
  • Coloque o retorno de falha de uma busca após o laço, para que os candidatos posteriores possam ser verificados.
  • Uma comparação pode ser retornada diretamente como um booleano.
  • Use return; sem valor para sair antecipadamente de um método void.
  • Código diretamente após um return incondicional no mesmo bloco é inalcançável.
3

Acompanhe variáveis e chamadas ao longo de um programa

Uma chamada de método não dá a um método auxiliar acesso a todas as variáveis do programa. Cada chamada tem seus próprios parâmetros e variáveis locais, e Java mantém esses valores em um registro de ativação separado. Use o escopo para determinar onde um nome é permitido, a passagem por valor para prever o que as atribuições podem alterar e a pilha de chamadas para acompanhar o trabalho ainda não concluído. Essas três ideias explicam por que duas variáveis podem ter o mesmo nome e armazenar valores diferentes.

3.1 Identifique onde cada variável pode ser usada

O escopo de uma variável é a região do código em que seu nome pode ser usado. Comece pelas chaves em torno de sua declaração: um nome local pertence a um método ou bloco específico.

As variáveis locais de quem chama permanecem em seu método
public static void main(String[] args) {
    int price = 20;
    printDouble(price);
}

public static void printDouble(int price) {
    System.out.println(price * 2);
}

O price de main e o parâmetro price de printDouble são variáveis distintas. O argumento fornece o valor necessário ao método auxiliar, portanto ele exibe 40.

Remover o parâmetro e chamar printDouble() não permite que o método auxiliar leia o price local de main. Seu corpo falharia com “cannot find symbol”. Chamar um método a partir de outro não une seus escopos. Métodos diferentes podem usar o nome count sem conectar suas variáveis.

Um bloco aninhado cria um escopo menor

Uma variável local pode ser usada de sua declaração até a chave de fechamento de seu bloco. Um parâmetro fica disponível em todo o corpo do método. Um contador declarado em for (int i = 0; i < 3; i++) pertence a esse laço; i não pode ser lido depois dele.

Para manter um resultado após um laço, declare-o antes do laço:

int sum = 0;
for (int i = 1; i <= 5; i++) {
    sum += i;
}
System.out.println(sum);

As somas fazem sum passar por 1, 3, 6, 10 e 15. A exibição final pode ler sum porque o bloco que o contém ainda não terminou. i é necessário apenas para o laço e permanece dentro de seu escopo.

Mover int sum = 0; para o corpo do laço cria um novo sum a cada passagem. Cada um começa em zero e desaparece no fim dessa passagem. Ele não pode manter uma soma acumulada nem ser exibido após o laço.

Verifique nomes e valores iniciais separadamente

Duas variáveis locais com o mesmo nome não podem ter escopos sobrepostos dentro de um método. Um método com um parâmetro x não pode declarar outra variável local x; um laço que declara i não pode declarar outro i em seu corpo. Renomeie a segunda variável ou use a existente.

Dois laços consecutivos podem declarar int i. O escopo do primeiro laço terminou antes da segunda declaração. As chaves, e não o arquivo inteiro, determinam essa reutilização.

Um nome permitido também precisa de um valor antes de ser lido. int total; total++; falha porque ++ precisa ler o valor anterior, e uma variável local não recebe valor inicial automático. Use int total = 0; para uma soma acumulada.

Mantenha uma variável local no menor bloco que precisa dela. Se um método precisa de informações de quem o chama, transforme essas informações em parâmetros. Se quem chama precisa de um resultado, retorne-o. Assim, o cabeçalho e o corpo do método mostram de onde vêm seus dados.

Principais conclusões

  • Um nome local fica disponível de sua declaração até o fim de seu bloco.
  • Um método chamado não pode ler pelo nome as variáveis locais de quem o chamou.
  • Declare um acumulador antes de um laço quando ele precisar manter um total ou ser lido depois.
  • Nomes locais não podem ter escopos sobrepostos dentro de um método, e variáveis locais precisam de valores antes do uso.

3.2 Compreenda que os valores dos argumentos são passados como cópias

Java passa argumentos por valor. No início de uma chamada, cada parâmetro recebe uma cópia do valor de seu argumento. Atribuir um valor ao parâmetro altera essa variável local.

Rastreie a cópia separadamente
public static void main(String[] args) {
    int score = 10;
    addBonus(score);
    System.out.println(score);
}

public static void addBonus(int score) {
    score = score + 5;
    System.out.println(score);
}

Há duas variáveis chamadas score. Acompanhe seus valores em cada ponto:

Momentoscore de mainscore de addBonus
Antes da chamada10Ainda não há chamada
Na entrada de addBonus1010
Após a atribuição do método auxiliar1015
Após o retorno do método auxiliar10A chamada terminou

O método auxiliar exibe 15, depois main exibe 10. Compartilhar um nome não faz as duas variáveis compartilharem o armazenamento. Renomear o parâmetro não alteraria esse comportamento.

Retorne o novo valor e armazene-o
public static int addBonus(int score) {
    return score + 5;
}

Com esta versão, escreva score = addBonus(score);. Java copia o valor antigo para o parâmetro, calcula 15, retorna esse valor e o atribui à variável de quem chamou. A atribuição em quem chama é a etapa que altera essa variável.

Um resultado também pode ser armazenado em outro lugar. Se triple(int n) multiplicar seu n local por 3 e retorná-lo, então int a = 4; int b = triple(a); deixa a igual a 4 e atribui a b o valor 12. Exibir a + " " + b mostra “4 12”.

Aplique a mesma regra a referências String

Uma variável String armazena uma referência a um objeto String. Java copia essa referência para um parâmetro String:

public static void exclaim(String text) {
    text = text + "!";
}

Se word de quem chama se referir a “hi”, exclaim(word); deixa word se referindo a “hi”. A concatenação cria uma nova String, e a atribuição altera apenas aquilo a que o parâmetro se refere. O conteúdo existente de uma String não pode ser alterado.

Para manter o novo texto, retorne text + "!" de um método String como exclaimed e depois escreva word = exclaimed(word);.

Para objetos mutáveis, como listas, uma referência copiada ainda pode apontar para o mesmo objeto. Um método pode alterar o conteúdo desse objeto por meio da referência copiada. Reatribuir o parâmetro ainda não pode fazer a variável de quem chamou se referir a outro objeto. A regra da referência copiada e a regra do número copiado são ambas passagem por valor.

Você pode reatribuir um parâmetro, mas uma variável local separada como result pode facilitar a leitura de um cálculo mais longo: ela mantém a entrada original disponível e mostra qual valor será retornado.

Principais conclusões

  • Cada parâmetro recebe uma cópia do valor de seu argumento.
  • Reatribuir um parâmetro deixa inalterada a variável de quem chamou.
  • Para manter um novo valor calculado, retorne-o e atribua-o em quem chamou.
  • Uma referência copiada pode acessar o mesmo objeto mutável, mas a reatribuição do parâmetro permanece local.

3.3 Acompanhe as chamadas de métodos na pilha de chamadas

A pilha de chamadas registra chamadas que começaram, mas ainda não terminaram. Cada chamada recebe um registro de ativação com seus parâmetros, suas variáveis locais e o ponto em que quem chamou continuará.

Empilhe um registro, conclua-o e remova-o

A pilha funciona pelo princípio último a entrar, primeiro a sair. A chamada mais recente fica no topo e é executada enquanto quem a chamou aguarda abaixo. Quando ela retorna, Java remove seu registro e retoma quem chamou.

public static void main(String[] args) {
    int total = totalSeconds(2, 30);
    System.out.println(total);
}

public static int totalSeconds(int minutes, int seconds) {
    int fromMinutes = toSeconds(minutes);
    return fromMinutes + seconds;
}

public static int toSeconds(int minutes) {
    return minutes * 60;
}

Acompanhe o trabalho ainda não concluído:

  1. main começa e chama totalSeconds(2, 30). Sua atribuição a total deve esperar.
  2. O novo registro tem minutes = 2 e seconds = 30. Ele chama toSeconds(minutes) e aguarda fromMinutes.
  3. toSeconds recebe seu próprio minutes = 2. Ele retorna 120 e seu registro é removido.
  4. totalSeconds armazena fromMinutes = 120, adiciona 30 e retorna 150. Seu registro é removido.
  5. main armazena total = 150 e exibe 150.

No ponto mais profundo, os registros de baixo para cima são main, totalSeconds e toSeconds. Ambos os métodos auxiliares têm um parâmetro chamado minutes, mas esses parâmetros ocupam registros diferentes. As variáveis locais de quem chama e está aguardando não ficam visíveis para o método acima dele.

Uma chamada posterior recebe um novo registro. Um contador local não se lembra de seu valor anterior após o término da chamada; o valor de retorno é o que pode levar um resultado de volta.

Leia um rastreamento da pilha a partir do erro

Uma exceção não tratada exibe um rastreamento da pilha que mostra onde o erro ocorreu e quais chamadas levaram até ele. Veja um arquivo completo:

public class Main {
    public static void main(String[] args) {
        report(300, 0);
    }

    public static void report(int meters, int minutes) {
        int speed = perMinute(meters, minutes);
        System.out.println(speed + " m per minute");
    }

    public static int perMinute(int meters, int minutes) {
        return meters / minutes;
    }
}

A primeira linha da saída é Exception in thread "main" java.lang.ArithmeticException: / by zero. Os registros abaixo dela são:

at Main.perMinute(Main.java:12)
at Main.report(Main.java:7)
at Main.main(Main.java:3)

O registro superior identifica a divisão inteira por zero. Os dois seguintes localizam as chamadas que levaram até ela. Os números de linha pertencem exatamente a esta disposição do arquivo; adicionar uma linha os altera.

A pilha tem espaço finito. Uma cadeia que continua adicionando chamadas sem permitir que terminem pode causar StackOverflowError. A visualização da pilha de um depurador permite examinar a mesma cadeia enquanto o programa está pausado em um ponto de interrupção, incluindo as variáveis separadas de cada chamada em espera.

Principais conclusões

  • Cada chamada empilha um novo registro; um retorno remove esse registro e retoma quem chamou.
  • A chamada inacabada mais recente é executada primeiro: na pilha, o último a entrar é o primeiro a sair.
  • Variáveis locais com o mesmo nome em registros diferentes são variáveis distintas.
  • Acompanhe um valor retornado de volta à expressão ou atribuição que o aguarda.
  • Leia um rastreamento da pilha a partir do registro do erro no topo em direção às chamadas abaixo.
  • Uma cadeia que continua adicionando registros pode esgotar a pilha.
4

Faça sobrecarga de métodos

Uma operação útil pode aceitar vários tipos de entrada. A sobrecarga permite que essas formas compartilhem um nome, mantendo uma lista de parâmetros distinta para cada uma. Primeiro, verifique se duas declarações realmente têm assinaturas diferentes. Depois, acompanhe a escolha do compilador em uma chamada: conte os argumentos, identifique seus tipos e compare as versões compatíveis. O tipo da variável que recebe o resultado não pode salvar uma chamada cujos argumentos não identificam uma sobrecarga adequada.

4.1 Escreva métodos sobrecarregados

A sobrecarga dá o mesmo nome a métodos com listas de parâmetros diferentes. Ela é útil quando os métodos realizam a mesma tarefa para quantidades ou tipos diferentes de entrada.

Compare assinaturas

Para esses métodos, uma assinatura consiste no nome e nos tipos dos parâmetros em ordem. A quantidade de parâmetros decorre dessa lista.

public static int max(int a, int b) {
    if (a > b) {
        return a;
    }
    return b;
}

public static int max(int a, int b, int c) {
    return max(max(a, b), c);
}

public static double max(double a, double b) {
    if (a > b) {
        return a;
    }
    return b;
}

As assinaturas são max(int, int), max(int, int, int) e max(double, double). max(3, 9) retorna 9 usando a primeira. max(3, 9, 5) chama a segunda: a chamada interna com dois valores int retorna 9, depois a chamada externa com dois valores int compara 9 e 5, também retornando 9. max(2.5, 1.0) usa a versão double e retorna 2.5.

Saiba quais alterações não contam

Alterar apenas o tipo de retorno não cria uma sobrecarga. Estes cabeçalhos entram em conflito:

public static int area(int w, int h)
public static double area(int w, int h)

Ambos têm a assinatura area(int, int). Java rejeita a declaração duplicada. Renomear os parâmetros para width e height também mantém a mesma assinatura: quem chama fornece valores por posição, não pelo nome do parâmetro.

A ordem de tipos diferentes conta. describe(String s, int n) e describe(int n, String s) são assinaturas distintas. Elas compilam juntas, mas quem chama precisa lembrar uma ordem fácil de confundir, portanto use esse par apenas quando ele ajudar no projeto.

Deixe uma sobrecarga mais curta fornecer um valor padrão

Java não fornece valores padrão para parâmetros em declarações de métodos. Uma sobrecarga mais curta pode chamar uma mais longa com um argumento fixo:

public static void printLine(int length, char symbol) {
    for (int i = 0; i < length; i++) {
        System.out.print(symbol);
    }
    System.out.println();
}

public static void printLine(int length) {
    printLine(length, '-');
}

printLine(5, '*'); exibe *****. printLine(4); entra no método mais curto, que chama o mais longo com 4 e '-', exibindo ----. O laço fica em um só lugar, portanto alterações na tarefa de exibição se aplicam às duas formas.

A biblioteca de Java também usa sobrecargas. System.out.println aceita um int, um double, um char, um boolean ou uma String por meio de versões diferentes. Math.abs e Math.max oferecem versões para int, long, float e double.

Mantenha um único significado para o nome compartilhado. Exibir um recibo e exibir uma etiqueta são tarefas diferentes; nomes claros como printReceipt e printLabel informam a quem chama qual tarefa será executada.

Principais conclusões

  • Sobrecargas compartilham um nome e diferem na quantidade, nos tipos ou na ordem dos tipos dos parâmetros.
  • Tipos de retorno e nomes de parâmetros não distinguem assinaturas.
  • Uma sobrecarga mais curta pode chamar uma mais longa com um argumento padrão fixo.
  • Use um nome sobrecarregado para uma tarefa com diferentes formas de entrada.

4.2 Preveja qual método sobrecarregado será executado

O compilador escolhe uma sobrecarga a partir da quantidade e dos tipos dos argumentos. Determine essa escolha antes de considerar como o valor retornado será usado.

Comece pelas correspondências exatas

Suponha que uma classe defina show(int x) e show(double x). show(5) usa a versão int porque o literal 5 é int. show(5.0) usa a versão double. Um valor inteiro escrito como 5.0 ainda é uma expressão double.

Para uma chamada com vários argumentos, compare o tipo em cada posição. Um candidato com a quantidade errada de argumentos não pode ser compatível.

Permita a conversão de ampliação quando necessário

Se existir apenas show(double x), show(5) é válido: o int é ampliado para 5.0. Os caminhos de ampliação de tipos primitivos incluem:

byte → short → int → long → float → double
char → int → long → float → double

Com show(long x) e show(double x), um argumento int escolhe long. Esse é o tipo de parâmetro compatível mais específico: um long pode ser ampliado para double, enquanto um double não pode ser ampliado de volta para long.

A ampliação é uma conversão numérica permitida; ela não garante que toda conversão desse tipo preserve todos os algarismos. Em particular, converter um long suficientemente grande em double pode arredondar seu valor. A conversão de int para double usada nos exemplos anteriores preserva exatamente todos os valores int.

Um char também tem valor numérico. Com letter(int code) e letter(String text), letter('A') chama a versão int com 65. Um caractere não se torna uma String para corresponder a um parâmetro. As aspas duplas em "A" criariam um argumento String.

Rejeite o estreitamento implícito

Se houver apenas show(int x), show(5.0) falha. Java não faz o estreitamento de um argumento double apenas porque seu valor é um número inteiro. show((int) 5.0) passa um int após uma conversão explícita.

Da mesma forma, versões de max para dois e três valores int não podem aceitar max(1). Nenhum candidato tem a quantidade necessária de parâmetros, portanto o compilador informa “no suitable method found”. Compare a lista de candidatos com os argumentos fornecidos.

Separe a escolha da sobrecarga da conversão do resultado

Considere int twice(int n) e double twice(double x). Em double d = twice(3);, o argumento seleciona a sobrecarga int. Essa chamada retorna 6, e a atribuição o amplia para 6.0. O destino d não seleciona a sobrecarga double.

Reconheça uma chamada ambígua
public static void combine(int a, double b) { }
public static void combine(double a, int b) { }

combine(1, 2) é compatível com a primeira após ampliar seu segundo argumento e com a segunda após ampliar seu primeiro. Nenhuma assinatura é mais específica nas duas posições. Java informa “reference to combine is ambiguous”; ele não escolhe a definição escrita primeiro.

combine(1, 2.0) é compatível apenas com (int, double), pois a outra assinatura precisaria de uma conversão de estreitamento de 2.0. Um tipo de argumento claro ou um conjunto melhor de sobrecargas elimina a ambiguidade.

Principais conclusões

  • Escolha uma sobrecarga pela quantidade e pelos tipos dos argumentos em tempo de compilação.
  • Uma correspondência exata prevalece; a ampliação pode tornar outra versão compatível.
  • Java não faz estreitamento implícito de argumentos numéricos de métodos.
  • A variável que recebe o resultado não escolhe a sobrecarga.
  • Ambiguidade significa que várias versões são compatíveis e nenhuma é mais específica para a chamada inteira.
5

Divida um programa em métodos

Os métodos de um programa devem revelar seu plano. Dê a cada método uma tarefa significativa, passe a ele os valores necessários e deixe que seu resultado alimente a etapa seguinte. Código repetido muitas vezes revela a falta de um método; um método longo muitas vezes revela várias tarefas misturadas. Planeje os cabeçalhos primeiro, construa pequenas partes com resultados conhecidos e conecte-as aos poucos. Isso facilita identificar tanto o fluxo de dados quanto o local de um novo defeito.

5.1 Atribua uma tarefa clara a cada método

Decomposição significa dividir um problema em tarefas menores e resolver cada tarefa em seu próprio método. Escolha tarefas cujos nomes ajudem alguém a entender o plano do programa.

Separe o cálculo da entrada e da saída

Um programa sobre um passeio de bicicleta precisa calcular a velocidade e apresentar um relatório. As duas tarefas usam os mesmos dados, mas têm funções diferentes:

public static double kilometersPerHour(double km, double hours) {
    return km / hours;
}

public static void printRideReport(double speed) {
    System.out.println("Speed: " + speed + " km/h");
}

Para um passeio de 150 km em 2 horas, o cálculo retorna 75.0. O método de relatório recebe esse valor e o exibe. Quem chama conecta as etapas:

double speed = kilometersPerHour(150, 2);
printRideReport(speed);

O método de cálculo não lê entrada do teclado nem exibe um relatório. Outro programa pode usá-lo para comparar passeios ou armazenar velocidades sem alterar seu corpo. Para testá-lo, chame-o com entradas conhecidas e compare o número retornado com o esperado.

Reconheça um método com tarefas demais

Um nome como readAndCheckAndPrint sugere várias ações. Outros indícios incluem seções marcadas por comentários, um corpo maior que uma tela e grupos de variáveis que atendem a finalidades sem relação entre si. Esses são motivos para examinar o método, não limites rígidos para a quantidade de linhas que ele pode ter.

Divida o método em um ponto que faça sentido. O código de entrada pode obter um valor, um método auxiliar com retorno booleano pode verificá-lo, um método de cálculo pode retornar um resultado e um método de relatório pode exibi-lo. Assim, main pode ser lido como uma breve descrição de como essas tarefas se conectam.

Métodos focados são mais fáceis de ler separadamente, reutilizar e testar. Se o formato de um relatório mudar, edite o método de relatório. Se um cálculo estiver errado, teste esse cálculo sem precisar digitar uma sessão inteira de entrada.

Deixe o cabeçalho explicar o fluxo de dados

Em kilometersPerHour(double km, double hours), o nome indica o resultado, os nomes dos parâmetros indicam as grandezas e o tipo de retorno double indica o tipo de resposta. Um breve comentário Javadoc pode acrescentar o significado das entradas e do resultado:

/**
 * Calculates a ride's average speed.
 * @param km distance in kilometers
 * @param hours elapsed time in hours, greater than zero
 * @return speed in kilometers per hour
 */

Coloque esse comentário diretamente acima do cabeçalho do método. Um comentário útil acrescenta informações como unidades ou um requisito para a entrada; ele não precisa narrar cada linha do corpo.

Um método auxiliar necessário apenas à sua própria classe pode ser private static. private impede que outras classes o chamem, enquanto o código da mesma classe ainda pode usá-lo. public static disponibiliza o método auxiliar para outras classes.

Separar cada instrução óbvia em seu próprio método também pode obscurecer o plano. Mantenha um método quando seu nome representar uma etapa significativa ou um cálculo reutilizável. Uma cadeia de métodos auxiliares que apenas repassam a mesma chamada acrescenta mais lugares a examinar sem explicar melhor a tarefa.

Principais conclusões

  • Decomponha um programa em tarefas significativas com nomes claros.
  • Métodos de cálculo recebem parâmetros e retornam resultados; métodos de relatório os exibem.
  • Métodos auxiliares focados podem ser reutilizados e testados separadamente.
  • Um cabeçalho e um breve comentário Javadoc podem informar entradas, unidades e resultado.
  • Use private static para métodos auxiliares que apenas sua própria classe deve chamar.
  • Divida onde um nome esclarece a tarefa, não em cada instrução individual.

5.2 Substitua código repetido por um método parametrizado

Código duplicado repete a mesma tarefa em mais de um lugar. Quando apenas os valores de entrada diferem, um método parametrizado pode manter o trabalho comum em um só lugar.

Encontre o cálculo comum

Suponha que um programa some de 1 a 10 e depois de 1 a 50:

int total1 = 0;
for (int i = 1; i <= 10; i++) {
    total1 += i;
}
System.out.println("Sum 1 to 10: " + total1);
int total2 = 0;
for (int i = 1; i <= 50; i++) {
    total2 += i;
}
System.out.println("Sum 1 to 50: " + total2);

Os dois laços começam em 1, adicionam valores a um total e param em um limite superior. Apenas esse limite muda. Um parâmetro n pode levá-lo a um cálculo compartilhado.

Extraia o método
public static int sumUpTo(int n) {
    int total = 0;
    for (int i = 1; i <= n; i++) {
        total += i;
    }
    return total;
}

n é a entrada variável. total e i são variáveis de trabalho que pertencem ao método auxiliar. Quem chama precisa da soma final, portanto o método auxiliar retorna um int.

Substitua as duas seções repetidas:

System.out.println("Sum 1 to 10: " + sumUpTo(10));
System.out.println("Sum 1 to 50: " + sumUpTo(50));

sumUpTo(10) retorna 55, e sumUpTo(50) retorna 1275. As linhas exibidas são “Sum 1 to 10: 55” e “Sum 1 to 50: 1275”, como antes. As descrições permanecem em quem chama; o laço realiza apenas o cálculo.

Verifique a extração em uma ordem definida
  1. Marque as instruções que realizam a tarefa repetida.
  2. Identifique cada valor que difere entre as cópias.
  3. Transforme esses valores em parâmetros com tipos adequados e retorne qualquer resultado necessário fora do método.
  4. Substitua cada cópia por uma chamada usando suas entradas originais.
  5. Execute as mesmas entradas antes e depois e compare o comportamento.

Alterar a estrutura do código preservando seu comportamento é refatoração. Deixar uma cópia original significa que uma correção posterior ainda terá dois lugares para atualizar. Mover uma exibição para dentro de um laço ou alterar o limite final de um laço muda o comportamento, mesmo que o código fique mais curto.

Quando duas diferenças têm tipos diferentes, use parâmetros correspondentes. Repetir textos diferentes quantidades diferentes de vezes sugere printRepeated(String text, int times); a palavra é uma String e a contagem é um int.

Código com aparência semelhante nem sempre realiza a mesma tarefa. Um parâmetro booleano que alterna um método entre cálculos sem relação entre si pode dificultar a interpretação das chamadas. Dê nomes diferentes a tarefas diferentes. Extraia a operação repetida apenas quando variar suas entradas preservar um significado claro.

Principais conclusões

  • Identifique a tarefa comum e transforme suas entradas variáveis em parâmetros.
  • Mantenha as variáveis de trabalho locais e retorne qualquer resultado necessário a quem chama.
  • Refatore cada cópia e compare o comportamento com as mesmas entradas.
  • Una cópias da mesma tarefa, não tarefas diferentes que apenas parecem semelhantes.

5.3 Projete um programa de forma descendente e teste cada método

O projeto descendente começa pela tarefa completa e a refina em chamadas de métodos menores. Decida o que cada chamada precisa e retorna antes de preencher todos os detalhes.

Planeje as etapas e os cabeçalhos

Um programa semanal de exercícios lê 7 durações diárias, soma-as e exibe um relatório. Seus métodos auxiliares podem ser planejados assim:

  • readMinutes(Scanner scanner, int day) retorna os minutos válidos de um dia.
  • isValidMinutes(int minutes) responde se a entrada está entre 0 e 1440.
  • formatDuration(int minutes) retorna texto com horas inteiras e minutos restantes.
  • averagePerDay(int total, int days) retorna uma média double.
  • printSummary(int totalMinutes, int days) exibe o relatório.

O mesmo Scanner é passado a cada chamada de entrada. Um método auxiliar como isValidMinutes não precisa ler a entrada por conta própria.

Use métodos provisórios durante o desenvolvimento

Um método provisório tem seu cabeçalho definitivo, mas um corpo mínimo temporário, como return 0;. Ele permite que o programa compile antes de o método auxiliar ser implementado. Substitua um método provisório, compile e verifique esse método antes de substituir o próximo. Um método provisório que compila ainda é trabalho inacabado; sua resposta fixa não pode verificar um cálculo real.

Veja o programa concluído:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int total = 0;
        for (int day = 1; day <= 7; day++) {
            total += readMinutes(scanner, day);
        }
        printSummary(total, 7);
    }

    public static int readMinutes(Scanner scanner, int day) {
        System.out.println("Minutes for day " + day + ":");
        int minutes = scanner.nextInt();
        while (!isValidMinutes(minutes)) {
            System.out.println("Enter minutes from 0 to 1440:");
            minutes = scanner.nextInt();
        }
        return minutes;
    }

    public static boolean isValidMinutes(int minutes) {
        return minutes >= 0 && minutes <= 1440;
    }

    public static String formatDuration(int minutes) {
        return minutes / 60 + " h " + minutes % 60 + " min";
    }

    public static double averagePerDay(int total, int days) {
        return (double) total / days;
    }

    public static void printSummary(int totalMinutes, int days) {
        System.out.println("Total: " + formatDuration(totalMinutes));
        System.out.println("Daily average: "
            + averagePerDay(totalMinutes, days) + " min");
        if (totalMinutes >= 150) {
            System.out.println("Weekly goal reached");
        }
    }
}

Para uma entrada inteira, readMinutes repete a verificação do intervalo até que o número seja válido. Com as entradas diárias 30, 45, 0, 60, 90, 45 e 45, o total é 315. A formatação produz “5 h 15 min”, a média é 45.0 minutos e o programa informa que sua meta semanal de 150 minutos foi atingida.

Verifique métodos pequenos e seus valores-limite

Chame cada método de cálculo com resultados conhecidos. formatDuration(0) deve resultar em “0 h 0 min”, 59 resulta em “0 h 59 min”, 60 resulta em “1 h 0 min” e 135 resulta em “2 h 15 min”. As entradas imediatamente abaixo de 60 e no próprio limite verificam a mudança de minutos para uma hora inteira.

Para isValidMinutes, teste -1, 0, 1440 e 1441. Os resultados esperados são false, true, true e false. Exibir os valores esperado e obtido lado a lado torna um erro visível. JUnit automatiza esse tipo de verificação.

O desenvolvimento ascendente começa pela escrita e pelo teste de pequenos métodos auxiliares e depois os une em etapas maiores. Você pode planejar de forma descendente e construir de forma ascendente: defina primeiro o fluxo de dados, comprove que os pequenos cálculos funcionam e depois verifique o programa integrado.

Principais conclusões

  • O projeto descendente transforma uma tarefa completa em chamadas e depois refina cada tarefa.
  • Decida as entradas e o tipo de retorno de cada método auxiliar antes de seu corpo.
  • Um método provisório preserva um cabeçalho planejado enquanto seu corpo ainda é temporário.
  • Teste resultados conhecidos e valores nos limites ou próximos deles.
  • Construa e verifique um método de cada vez e depois teste o programa integrado.
  • O desenvolvimento ascendente constrói pequenos métodos auxiliares antes de combiná-los.

Exercícios resolvidos de Métodos em Java

5 Lições Interativas

1

Construa um método reutilizável para exibir linhas

11 passos
Defina um método auxiliar, rastreie suas chamadas e adicione parâmetros para entradas variáveis.
  1. 1
    IntroduçãoTransforme uma ação repetida em uma chamada

    Um relatório precisa de um separador curto em vários lugares. Dar um nome de método a essa ação permite que o relatório solicite um separador sem repetir as instruções de exibição. Essa ação nomeada é um método, e uma definição atende a todas as chamadas.

    Comece com um separador fixo. Depois permita que quem chama escolha sua largura e seu símbolo com parâmetros. Acompanhe a definição, a chamada e os valores fornecidos como três partes diferentes da tarefa.

  2. 2
    ExplicaçãoLeia o cabeçalho de um método
    public static void printDivider() {
        System.out.println("====");
    }
    

    printDivider é o nome. public permite chamadas de outras classes; static significa que não é necessário um objeto. void indica que nenhum valor é devolvido, e () indica que nenhuma entrada é necessária.

    A instrução dentro das chaves é o corpo. Nada é exibido apenas porque essa definição existe.

  3. 3
    DicaColoque o método auxiliar ao lado de main

    Em uma classe clássica, main e printDivider são métodos separados dentro das mesmas chaves da classe. Feche o corpo de main antes de iniciar o cabeçalho do método auxiliar.

    Um método auxiliar pode aparecer acima ou abaixo de main; sua posição não determina quando ele é executado. Uma definição colocada dentro de main é rejeitada. Verifique primeiro as chaves quando um cabeçalho de método produzir “illegal start of expression”.

  4. 4
    ExemploAcompanhe a primeira chamada

    Suponha que main contenha:

    System.out.println("Items");
    printDivider();
    System.out.println("End");
    

    A execução primeiro exibe “Items”. A chamada entra em printDivider, que exibe “====”. Quando o método auxiliar termina, main continua em sua próxima instrução e exibe “End”.

    O corpo do método auxiliar é executado entre as duas instruções de quem chamou, exatamente onde a chamada aparece.

  5. 5
    DesafioColoque um segundo separador

    main chama printDivider();, exibe "A" e chama printDivider(); novamente. Quais três linhas aparecem?

    ---reveal---

    As linhas são “====”, “A” e “====”. Cada chamada entra no mesmo corpo do método auxiliar, exibe uma vez e retorna ao seu próprio ponto em main.

    Escrever printDivider; não faria uma chamada. Mesmo sem argumentos, os parênteses são obrigatórios.

  6. 6
    ExplicaçãoUse a largura como entrada

    Substitua o corpo fixo por um laço:

    public static void printDivider(int length) {
        for (int i = 0; i < length; i++) {
            System.out.print("=");
        }
        System.out.println();
    }
    

    length é um parâmetro declarado no cabeçalho. Em printDivider(6);, o argumento 6 se torna seu valor inicial. Seis passagens pelo laço exibem seis símbolos antes de a linha terminar.

  7. 7
    ExemploAvalie uma expressão antes da chamada
    int sections = 3;
    printDivider(sections + 2);
    

    Primeiro, avalie sections + 2 para obter 5. Depois entre no método auxiliar com seu parâmetro length = 5. Seu laço exibe “=====” .

    sections e length não precisam ter o mesmo nome. Um parâmetro recebe o valor avaliado do argumento; quem chama não coloca o tipo na chamada.

  8. 8
    ExemploAdicione uma segunda entrada variável

    Para escolher também o símbolo, use:

    public static void printDivider(int length, char symbol) {
        for (int i = 0; i < length; i++) {
            System.out.print(symbol);
        }
        System.out.println();
    }
    

    A chamada printDivider(3, '+'); passa 3 para length e '+' para symbol, exibindo “+++”. Cada parâmetro precisa de seu próprio tipo no cabeçalho.

  9. 9
    DicaVerifique a quantidade, a ordem e o tipo

    Uma chamada deve fornecer um valor compatível para cada parâmetro. Agora falta o símbolo em printDivider(3);, enquanto printDivider("3", '+'); fornece texto onde é necessário um int.

    Java pode ampliar um int para double para um parâmetro double. Ele não pode estreitar implicitamente 3.7 para adequá-lo a esse parâmetro int. A conversão explícita (int) 3.7 fornece 3 ao descartar a parte fracionária.

  10. 10
    DesafioPreveja uma chamada com parâmetros

    Usando o método auxiliar com dois parâmetros, qual linha isto exibe?

    int width = 4;
    printDivider(width - 1, '#');
    

    ---reveal---

    Ele exibe “###”. A expressão é avaliada como 3, depois o primeiro parâmetro recebe essa contagem e o segundo recebe '#'. O laço é executado três vezes.

    A chamada é uma instrução, portanto termina com ponto e vírgula. Suas expressões de argumento contêm valores, não declarações de parâmetros.

  11. 11
    RecapitulaçãoLeia a ação e suas entradas

    Uma definição dá a uma tarefa um cabeçalho e um corpo; uma chamada a executa e depois retoma quem chamou. Mantenha as definições dentro da classe e fora de outros métodos.

    Os parâmetros descrevem as entradas necessárias. As chamadas fornecem argumentos avaliados na ordem correspondente, com a quantidade correta e tipos compatíveis.

2

Retorne respostas e conclua buscas

13 passos
Use valores de retorno em quem chama e depois rastreie retornos antecipados e caminhos de retorno completos.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoDevolva um resultado a quem chamou
  2. 2
    ExplicaçãoFaça uma chamada representar um valor
  3. 3
    Ideia-chaveUma exibição não pode fornecer valor a uma atribuição
  4. 4
    ExemploMantenha a parte fracionária
  5. 5
    DesafioUse o resultado em outra expressão
  6. 6
    ExemploRetorne texto formatado
  7. 7
    ExplicaçãoUm return encerra esta chamada
  8. 8
    DicaVerifique o caminho que não entra no if
  9. 9
    ExemploEscreva uma busca com um resultado de falha
  10. 10
    ExemploRastreie a busca até seu término
  11. 11
    DesafioEncontre uma falha prematura
  12. 12
    DesafioConecte um resultado de busca a uma condição
  13. 13
    RecapitulaçãoAcompanhe a resposta e o ponto de parada
3

Mantenha separadas as variáveis de cada chamada

15 passos
Rastreie escopo, valores copiados e registros de ativação em espera ao longo de um pequeno programa.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoIdentifique cada variável por sua chamada
  2. 2
    ExplicaçãoUm método auxiliar vê suas próprias variáveis locais
  3. 3
    ExemploMantenha um total fora do laço
  4. 4
    DesafioSepare escopo de inicialização
  5. 5
    ExemploCopie um número para um parâmetro
  6. 6
    ExemploAtribua o novo valor retornado
  7. 7
    DesafioPreveja uma segunda chamada
  8. 8
    ConexãoReferências copiadas seguem a mesma regra
  9. 9
    ExemploInicie um cálculo externo
  10. 10
    ExemploPause quem chamou e empilhe outro registro
  11. 11
    ExemploLeve os resultados de volta pela pilha
  12. 12
    DicaInterprete um erro a partir do registro superior
  13. 13
    DesafioEncontre o trabalho em espera
  14. 14
    DesafioConecte cópias aos resultados da pilha
  15. 15
    RecapitulaçãoMantenha nomes, valores e registros distintos
4

Escolha o método sobrecarregado adequado

12 passos
Compare assinaturas, reutilize uma sobrecarga mais longa e resolva chamadas a partir dos tipos dos argumentos.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoUma tarefa, várias formas de entrada
  2. 2
    ExplicaçãoIdentifique uma assinatura
  3. 3
    Ideia-chaveUm tipo de retorno não pode criar uma sobrecarga
  4. 4
    ExemploDelegue à versão completa
  5. 5
    DesafioVerifique uma terceira declaração proposta
  6. 6
    ExplicaçãoEscolha uma correspondência numérica exata
  7. 7
    ExemploUse ampliação sem estreitamento
  8. 8
    ExemploSepare a chamada de sua atribuição
  9. 9
    ExemploCompare cada posição dos argumentos
  10. 10
    DicaUse a lista de candidatos para diagnosticar uma chamada
  11. 11
    DesafioEscolha uma versão e depois use seu resultado
  12. 12
    RecapitulaçãoVerifique as definições antes das chamadas
5

Construa um pequeno relatório com métodos auxiliares testados

16 passos
Separe tarefas, extraia código repetido e planeje um programa completo em torno de métodos testados.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoTransforme um relatório em pequenas tarefas
  2. 2
    ExplicaçãoNomeie a tarefa antes de escrever o corpo
  3. 3
    ExemploTorne o cálculo reutilizável
  4. 4
    ExemploDê à saída seu próprio método
  5. 5
    DesafioReutilize um cálculo sem relatório
  6. 6
    ExplicaçãoDescubra o que muda no código repetido
  7. 7
    ExemploEscolha o cabeçalho extraído
  8. 8
    ExemploColoque o laço compartilhado em um só lugar
  9. 9
    DesafioPreserve a última repetição
  10. 10
    ExplicaçãoPlaneje o programa de cima para baixo
  11. 11
    DicaUse um método provisório apenas durante o desenvolvimento
  12. 12
    ExemploPasse o mesmo leitor de entrada
  13. 13
    ExemploVerifique o cálculo antes de conectá-lo
  14. 14
    ExemploVerifique uma sequência de entradas no programa integrado
  15. 15
    DesafioLocalize um erro de conexão
  16. 16
    RecapitulaçãoConstrua partes significativas e conecte-as

Questões de Métodos em Java

40 Questões de Prática em 4 conjuntos

Conjunto 1: Rastreie métodos auxiliares e corrija os limites entre métodos10 Questões de Prática

Questão 1 de 10

Estas sobrecargas estão na mesma classe. Qual valor é armazenado em answer?

public static int adjust(int n) { return n + 1; }
public static double adjust(double n) { return n + 0.5; }
double answer = adjust(6);
  1. 6.5
  2. 6.0
  3. 7.5
  4. 7.0
Mostrar respostaOcultar resposta
Resposta: D
O argumento 6 é um int, portanto a sobrecarga int retorna 7. A atribuição então amplia esse resultado para 7.0. O destino double não seleciona a sobrecarga double; 6.5 seria o resultado de passar um argumento double como 6.0.

Questão 2 de 10

Qual sequência de linhas é exibida?

public static void frame() {
    System.out.println("Open");
    mark();
    System.out.println("Close");
}
public static void mark() {
    System.out.println("Mark");
}

main chama frame(); e depois exibe "Done".

  1. “Open”, “Close”, “Mark”, “Done”
  2. “Mark”, “Open”, “Close”, “Done”
  3. “Open”, “Mark”, “Done”, “Close”
  4. “Open”, “Mark”, “Close”, “Done”
Mostrar respostaOcultar resposta
Resposta: D
frame exibe “Open”, pausa para executar mark e depois retoma a execução para exibir “Close”. Somente após o término de frame, main exibe “Done”. A chamada de mark é executada onde aparece no corpo; ela não é adiada até o fim de frame.

Questão 3 de 10

Um método tem o cabeçalho public static void repeat(int count). Qual valor chega a count em repeat((int) 3.9 + 2);?
  1. 3
  2. 5
  3. 6
  4. 5.9
Mostrar respostaOcultar resposta
Resposta: B
A conversão explícita se aplica a 3.9, produzindo o int 3. Java então adiciona 2, resultando no valor de argumento 5 antes de entrar em repeat. A conversão trunca a parte fracionária positiva; ela não arredonda 3.9 para 4, o que produziria 6.

Questão 4 de 10

Qual valor é atribuído a result?

public static int addTwo(int n) {
    return n + 2;
}
public static int product(int a, int b) {
    return a * b;
}
int result = product(addTwo(4), addTwo(addTwo(1)));
  1. 24
  2. 42
  3. 30
  4. 18
Mostrar respostaOcultar resposta
Resposta: C
O primeiro argumento se torna 6. Para o segundo, addTwo(1) retorna 3, depois a chamada externa addTwo(3) retorna 5; portanto, product(6, 5) retorna 30. Multiplicar 6 por 3 ignoraria a chamada externa em torno do segundo argumento.

Questão 5 de 10

O método deve retornar o primeiro valor par em um intervalo inclusivo, ou -1 se nenhum existir. Ele retorna -1 incorretamente para (9, 12). Qual alteração corrige a busca?

public static int firstEven(int start, int end) {
    for (int n = start; n <= end; n++) {
        if (n % 2 == 0) {
            return n;
        } else {
            return -1;
        }
    }
    return -1;
}
  1. Remover o ramo else e manter o return final.
  2. Substituir o return do else por return n + 1;.
  3. Mover o return final para dentro do laço após o if/else.
  4. Alterar o teste do if para n % 2 != 0.
Mostrar respostaOcultar resposta
Resposta: A
O primeiro candidato, 9, é ímpar, mas isso não é motivo para encerrar a busca: 10 é uma correspondência posterior. Remover o ramo else permite que o laço continue. Retornar n + 1 pareceria corrigir essa entrada, mas poderia retornar um valor fora de um intervalo que contém apenas um número ímpar.

Questão 6 de 10

Um método auxiliar precisa do número armazenado na variável local pages de main. Como os dados devem chegar ao método auxiliar?
  1. Declarar outro pages não inicializado no método auxiliar.
  2. Mover o método auxiliar para abaixo de main na classe.
  3. Manter a chamada do método auxiliar apenas no escopo de pages.
  4. Adicionar um parâmetro e passar pages como argumento.
Mostrar respostaOcultar resposta
Resposta: D
Um método auxiliar não pode ler pelo nome a variável local de main. Dê a ele um parâmetro e passe o valor ao chamá-lo. Fazer a chamada enquanto pages está no escopo disponibiliza o argumento em main, mas não faz o corpo do método auxiliar compartilhar esse escopo.

Questão 7 de 10

Qual valor retorna a main a partir de outer(4)?

public static int outer(int n) {
    int saved = n;
    int changed = inner(n + 1);
    return saved + changed;
}
public static int inner(int n) {
    n *= 2;
    return n - 1;
}
  1. 14
  2. 13
  3. 19
  4. 9
Mostrar respostaOcultar resposta
Resposta: B
outer mantém saved = 4 e chama inner(5). O registro interno dobra seu próprio n para 10 e retorna 9, portanto o registro externo que aguardava calcula 4 + 9 = 13. Usar o n interno como se ele substituísse saved misturaria variáveis de registros separados.

Questão 8 de 10

O método printBorder(int length, char symbol), com dois argumentos, já contém o laço de exibição. Como printBorder(int length) deve fornecer '#' como padrão sem duplicar o laço?
  1. Chamar printBorder(length, '#'); em seu corpo.
  2. Adicionar char symbol = '#' como parâmetro padrão no cabeçalho.
  3. Chamar printBorder('#', length); em seu corpo.
  4. Chamar printBorder(length); em seu corpo.
Mostrar respostaOcultar resposta
Resposta: A
O método mais curto deve chamar a versão existente com dois argumentos, usando o mesmo comprimento e o caractere padrão na segunda posição. Java não tem sintaxe de parâmetro padrão em uma declaração. Chamar o método de um argumento a partir dele mesmo não alcançaria o laço da versão mais longa.

Questão 9 de 10

Dois blocos de código calculam áreas de retângulos, um usando 8 * 3 e outro usando 11 * 4. Ambos os resultados são necessários para comparações posteriores. Qual cabeçalho de método auxiliar é adequado para extrair esse cálculo compartilhado?
  1. public static void area(int width, int height)
  2. public static int area(int width)
  3. public static int area(int width, int height)
  4. public static int area()
Mostrar respostaOcultar resposta
Resposta: C
As duas dimensões variam, portanto o método auxiliar precisa de parâmetros para largura e altura. As comparações posteriores precisam da área calculada, então ele deve retornar um resultado int. Um método void poderia exibir a área, mas isso não forneceria o valor numérico necessário a quem chamou.

Questão 10 de 10

O que torna public static int countItems(int limit) { return 0; } um método provisório útil?
  1. Ele comprova que todas as contagens de itens estão corretas.
  2. Ele elimina a necessidade de testar o método concluído.
  3. Ele permite que as chamadas compilem antes de o corpo real estar pronto.
  4. Ele fornece a Java um valor padrão para o parâmetro.
Mostrar respostaOcultar resposta
Resposta: C
O método provisório já tem o nome, o parâmetro e o tipo de retorno planejados, portanto as chamadas ao redor podem compilar enquanto seu cálculo não está concluído. Seu zero fixo não comprova o comportamento correto; o corpo real deve substituí-lo e ser verificado com resultados esperados conhecidos.
Conjunto 2: Chamadas, valores e pequenas etapas de um programa10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Uma classe Java clássica tem um método main e precisa de um novo método printMenu. Onde a nova definição deve ficar?
  1. Dentro de main, após sua última instrução.
  2. Dentro da classe, fora de todos os outros métodos.
  3. Fora da classe, após sua chave de fechamento.
  4. Dentro do método que precisa chamá-lo.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Qual linha esta chamada exibe?

public static void showPair(int rows, int columns) {
    System.out.println(rows + ":" + columns);
}
int width = 7;
showPair(3, width - 2);
  1. 5:3
  2. 3:7
  3. 7:3
  4. 3:5
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Qual valor halfTotal(8, 5) retorna?

public static double halfTotal(int a, int b) {
    return (a + b) / 2;
}
  1. 6.0
  2. 6.5
  3. 13.0
  4. 7.0
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Por que este método não compila?

public static String label(int n) {
    if (n >= 0) {
        return "ready";
    }
}
  1. O valor de retorno deve ser exibido primeiro.
  2. A comparação não pode aparecer em um método.
  3. Entradas negativas chegam ao fim sem um valor.
  4. Métodos String não podem retornar dentro de um if.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Um laço deve somar os inteiros de 2 a 4 e depois exibir o total. Qual declaração deve substituir o comentário?

// declaration here
for (int i = 2; i <= 4; i++) {
    total += i;
}
System.out.println(total);
  1. int total;
  2. int total = 0;
  3. int total = 2;
  4. int total = i;
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Quais dois números são exibidos, em ordem?

public static void lower(int level) {
    level -= 3;
    System.out.println(level);
}
int level = 14;
lower(level);
System.out.println(level);
  1. 11, depois 14
  2. 11, depois 11
  3. 14, depois 11
  4. 14, depois 14
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Uma classe já declara public static int scale(int value). Qual cabeçalho adicional entraria em conflito com sua assinatura?
  1. public static int scale(int value, int factor)
  2. public static double scale(double value)
  3. public static long scale(long value)
  4. public static double scale(int amount)
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Uma classe tem show(int n) e show(double n). Qual método é executado para show(12.0)?
  1. show(int), com 12
  2. Ambos, com 12.0
  3. show(double), com 12.0
  4. Nenhum; a chamada é ambígua
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Um programa de rotas precisa calcular uma velocidade média e exibir um relatório. Qual divisão torna o cálculo da velocidade reutilizável em um programa que compara rotas?
  1. Calcular e retornar a velocidade; exibi-la em outro método.
  2. Calcular e exibir a velocidade; não retornar valor do método.
  3. Ler e exibir a velocidade; recalculá-la em cada chamada.
  4. Calcular e exibir a velocidade; retornar o título do relatório.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Um programa deve aceitar durações de tarefas de 0 a 90 minutos e informar sua média. Atualmente, ele usa estes métodos auxiliares. Quais duas chamadas com entradas podem revelar os dois defeitos independentes?

public static boolean valid(int m) {
    return m > 0 && m <= 90;
}
public static double mean(int total, int count) {
    return total / count;
}
  1. valid(45) e mean(8, 2)
  2. valid(0) e mean(7, 2)
  3. valid(91) e mean(8, 2)
  4. valid(90) e mean(7, 2)
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Conjunto 3: Conecte argumentos, caminhos de retorno e projeto10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Um método auxiliar deve poder ser chamado apenas por código dentro da mesma classe. Qual modificador de acesso seu cabeçalho estático deve usar?
  1. public
  2. static
  3. void
  4. private
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Uma pessoa programadora escreve isto dentro de uma classe. Por que a definição do método auxiliar é rejeitada?

public static void main(String[] args) {
    public static void printTitle() {
        System.out.println("Schedule");
    }
}
  1. Um método auxiliar deve ficar acima de main.
  2. Um método auxiliar de exibição deve retornar uma String.
  3. O método auxiliar está definido dentro de outro método.
  4. O nome do método auxiliar deve começar com maiúscula.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

O método retorna a quantidade de grupos inteiros. O que groups(5, 18) retorna?

public static int groups(int groupSize, int items) {
    return items / groupSize;
}
  1. 3
  2. 0
  3. 3.6
  4. 4
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Um método auxiliar de calendário é escrito como abaixo. Qual par de resultados é retornado por leap(2100) e depois por leap(2400)?

public static boolean leap(int year) {
    return (year % 4 == 0 && year % 100 != 0)
        || year % 400 == 0;
}
  1. true, depois true
  2. false, depois true
  3. false, depois false
  4. true, depois false
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Qual texto é exibido por quem chama?

public static void tag(String name) {
    name = name + "-checked";
}
String label = "parcel";
tag(label);
System.out.println(label);
  1. “parcel-checked”
  2. “checked”
  3. “parcelparcel”
  4. “parcel”
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Um relatório de erro começa com ArithmeticException: / by zero e estes registros. Onde ocorreu a divisão que falhou?

at Main.unitCount(Main.java:23)
at Main.printLoad(Main.java:15)
at Main.main(Main.java:5)
  1. Em main, na linha 5.
  2. Em printLoad, na linha 15.
  3. Em unitCount, na linha 23.
  4. Após unitCount retornar à linha 15.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Uma classe declara public static void describe(String name, int count). Qual cabeçalho adiciona uma sobrecarga válida alterando a ordem dos tipos dos parâmetros?
  1. public static int describe(String name, int count)
  2. public static void describe(int count, String name)
  3. public static void describe(String title, int number)
  4. private static void describe(String name, int count)
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Qual linha é exibida por esta chamada? O caractere 'B' tem valor numérico 66.

public static int code(int n) { return n + 1; }
public static String code(String s) { return s + "!"; }
double result = code('B');
System.out.println(result);
  1. 67.0
  2. 66.0
  3. “B!”
  4. 67
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

O programa original exibe os totais 20 e 30, nessa ordem. Após a extração, ele usa este método auxiliar. Como as duas chamadas devem ser escritas para preservar esses totais?

public static int sumMultiples(int factor, int count) {
    int total = 0;
    for (int i = 1; i <= count; i++) {
        total += factor * i;
    }
    return total;
}

O primeiro laço original somava 2, 4, 6 e 8. O segundo somava 5, 10 e 15.

  1. sumMultiples(2, 4) depois sumMultiples(5, 3)
  2. sumMultiples(4, 2) depois sumMultiples(3, 5)
  3. sumMultiples(2, 8) depois sumMultiples(5, 15)
  4. sumMultiples(2, 3) depois sumMultiples(5, 2)
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Um programa lê cinco contagens diárias, soma-as e exibe uma média. Os cabeçalhos planejados dos métodos auxiliares estão abaixo. Qual conexão em main permite que a etapa de relatório receba todos os dados necessários?

public static int readCount(Scanner scanner, int day)
public static double average(int total, int days)
public static void printReport(int total, int days)

O Scanner já foi criado.

  1. Sobrescrever um count no laço; chamar printReport(count, 5).
  2. Acumular as cinco contagens retornadas; chamar printReport(total, 5).
  3. Exibir cada contagem retornada; chamar printReport(0, 5) depois.
  4. Somar os números dos dias no laço; chamar printReport(total, 5).
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Conjunto 4: Diagnostique interações completas entre métodos10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Qual linha é exibida?

public static int next(int n) { return n + 1; }
public static double half(int n) { return n / 2.0; }
int n = 5;
next(n);
double result = half(next(n)) + n;
System.out.println(result);
  1. 9.5
  2. 7.5
  3. 3.0
  4. 8.0
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Qual valor locate(5) retorna?

public static int locate(int limit) {
    int total = 0;
    for (int n = 1; n <= limit; n++) {
        total += n;
        if (total > 8) {
            return n;
        }
    }
    return -1;
}
  1. 4
  2. 5
  3. 10
  4. 15
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

O código deve totalizar os pesos e exibir sua soma após o laço. Atualmente, ele não compila. Qual alteração corrige o problema de escopo e preserva uma soma acumulada?

for (int box = 1; box <= 3; box++) {
    int total = 0;
    total += box * 2;
}
System.out.println(total);
  1. Mover apenas println(total) para dentro do laço.
  2. Declarar int total; antes do laço e remover a declaração interna.
  3. Mover int total = 0; para antes do laço e remover a declaração interna.
  4. Declarar int total = 0; após o laço, antes da exibição.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Qual par de valores é exibido como a:b?

public static int shift(int n) {
    n += 4;
    return n;
}
int a = 2;
int b = shift(a);
a = shift(b);
System.out.println(a + ":" + b);
  1. 6:10
  2. 10:6
  3. 10:10
  4. 6:6
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

No ponto marcado, quais são os valores das duas variáveis locais chamadas saved, lendo primeiro o registro externo e depois o interno?

public static int outer(int n) {
    int saved = n + 2;
    return inner(saved) + saved;
}
public static int inner(int n) {
    int saved = n * 3;
    // program pauses here
    return saved;
}

main chamou outer(5).

  1. 7 e 21
  2. 21 e 21
  3. 5 e 15
  4. 7 e 7
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Um programa continua iniciando novas chamadas sem deixar as existentes terminarem. Qual erro pode ocorrer quando não resta espaço na pilha?
  1. ArithmeticException
  2. “missing return statement”
  3. “cannot find symbol”
  4. StackOverflowError
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Os métodos abaixo estão declarados em uma classe. O que acontece em double result = merge(4, 9);?

public static int merge(int a, double b) { return a; }
public static double merge(double a, int b) { return b; }
public static double merge(double a, double b) { return a + b; }
  1. O destino double seleciona (double, int) e armazena 9.0.
  2. A chamada é ambígua entre as duas versões de tipos mistos.
  3. O primeiro argumento int seleciona (int, double) e armazena 4.0.
  4. A versão apenas com double é selecionada e armazena 13.0.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Um cálculo de sensor é útil, mas seu método atual também exibe uma longa mensagem de status. Um segundo código que o chama precisa do número sem essa mensagem. Qual projeto permite que ambos compartilhem um método de cálculo e escolham sua própria saída?
  1. Adicionar uma segunda cópia do cálculo sem a exibição.
  2. Renomear o método existente para descrever ambas as ações.
  3. Retornar o número e mover a exibição para quem gera o relatório.
  4. Tornar público o método combinado para que ambos possam usá-lo.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Dois blocos exibem um rótulo seguido de uma linha por item. O primeiro exibe "Crate" com itens numerados de 1 a 2; o segundo exibe "Bag" com itens numerados de 1 a 4. Qual corpo extraído preserva esse formato para printItems(String label, int count)?
  1. Exibir label dentro de um laço que começa em 0 enquanto i < count; não exibir números.
  2. Exibir label uma vez; percorrer de 1 enquanto i < count e exibir i.
  3. Exibir label uma vez; percorrer de 0 enquanto i <= count e exibir i.
  4. Exibir label uma vez; percorrer de 1 enquanto i <= count e exibir i.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Um método auxiliar deve retornar uma média diária decimal:

public static double dailyAverage(int total, int days) {
    return total / days;
}

Por que verificar apenas (24, 6) não revela seu defeito aritmético?

  1. Essa divisão é exata, portanto o truncamento não perde parte fracionária.
  2. O método amplia os dois operandos int antes de fazer a divisão.
  3. Essa entrada testa um quociente com parte fracionária diferente de zero.
  4. O resultado é depois arredondado para o inteiro mais próximo.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Travou em uma questão sua? Ajuda com Tarefas

Termos-Chave

51 Termos-Chave, cada um com sua definição

A

Acumulador
Um acumulador é uma variável que mantém um resultado acumulado enquanto um laço combina valores sucessivos nesse resultado.
Declare sum antes de um laço para que cada iteração adicione ao total mantido da passagem anterior.
Argumento
Um argumento é uma expressão fornecida em uma chamada de método cujo valor avaliado é passado a um parâmetro correspondente.
Em printRepeated("go", 4), os argumentos fornecem o texto e a quantidade de repetições.
Assinatura do método
A assinatura de um método, para esses métodos, é seu nome e os tipos dos parâmetros em ordem; tipos de retorno e nomes de parâmetros não a distinguem.
Alterar width para w deixa area(int, int) inalterada e não pode criar uma nova sobrecarga.

B

Bloco
Um bloco é um grupo de instruções delimitado por chaves que pode formar o corpo de um método, o corpo de um laço ou um ramo condicional.
Declarar um contador dentro de um bloco if mantém esse nome local até a chave de fechamento do bloco.

C

Cabeçalho do método
Um cabeçalho de método declara o nome, os modificadores, o tipo de retorno e os parâmetros de um método antes do início de seu corpo.
O cabeçalho public static void greet() descreve uma ação que pode ser chamada sem entrada e sem valor de retorno.
Caso de valor-limite
Um caso de valor-limite testa uma entrada em um limite ou ao lado dele, onde o comportamento esperado de um método muda, ajudando a revelar erros nos extremos.
Para um intervalo válido de 0 a 1440, verifique -1, 0, 1440 e 1441 como entradas separadas.
Chamada ambígua
Uma chamada ambígua é compatível com várias sobrecargas, mas não tem uma única correspondência mais específica, portanto o compilador não consegue selecionar uma delas.
Os pares (int, double) e (double, int) tornam ambígua uma chamada com dois argumentos int.
Chamada aninhada
Uma chamada aninhada é uma chamada de método usada dentro de outra chamada, de modo que seu resultado deve ser obtido antes de o método externo ser executado.
Em Math.max(sum(2, 6), 5), o resultado 8 se torna o primeiro argumento de Math.max.
Chamada de método
Uma chamada de método é uma expressão que nomeia um método e fornece seus argumentos entre parênteses para invocar seu corpo.
A instrução printHeader(); executa o método que exibe o cabeçalho naquele ponto de quem chamou.
Código duplicado
Código duplicado repete instruções iguais ou quase iguais, deixando vários lugares para atualizar quando a tarefa compartilhada muda.
Dois laços de soma com limites superiores diferentes podem muitas vezes ser substituídos por um método auxiliar e duas chamadas.
Conversão de ampliação
Uma conversão de ampliação altera um valor para um tipo mais amplo permitido, possibilitando que um argumento int seja aceito por um parâmetro double.
Passar 12 para um parâmetro double fornece a ele 12.0 sem exigir conversão explícita.
Conversão de estreitamento
Uma conversão de estreitamento altera um valor numérico para um tipo mais restrito e pode perder informações; chamadas de métodos não a realizam implicitamente.
Passar 9.0 para um parâmetro int falha sem uma conversão explícita, mesmo que o valor não tenha parte fracionária.
Conversão explícita de tipo
Uma conversão explícita de tipo é uma conversão escrita com o tipo de destino entre parênteses antes da expressão a ser convertida.
A expressão (int) 4.9 fornece 4 a um parâmetro int ao descartar a parte fracionária.
Corpo do método
Um corpo de método é o bloco delimitado por chaves que contém as instruções executadas quando o método é chamado.
A chamada entra no corpo, executa suas instruções e depois continua em quem chamou e está aguardando.
Correspondência exata
Uma correspondência exata ocorre quando os tipos dos argumentos já correspondem aos tipos dos parâmetros de um método sem conversão.
Com show(int) e show(double), show(9) tem uma correspondência exata com a versão int.

D

Decomposição
A decomposição divide o problema de um programa em tarefas menores e significativas, cada uma podendo ser implementada como um método focado.
Um relatório de passeio pode separar a obtenção de entradas, o cálculo de uma velocidade e a exibição do resultado.
Desenvolvimento ascendente
O desenvolvimento ascendente constrói e testa primeiro métodos pequenos e depois os combina nas etapas maiores do programa.
Teste uma verificação de validade e um formatador separadamente antes de usá-los em um programa completo de relatório.
Desenvolvimento incremental
O desenvolvimento incremental adiciona e verifica uma pequena parte de código funcional de cada vez, facilitando a localização da causa de um novo erro.
Implemente um método auxiliar, compile-o, teste resultados conhecidos e depois conecte-o à próxima parte.

E

Escopo
O escopo de uma variável é a região do texto do programa em que seu nome pode ser usado legalmente para se referir a essa variável.
Um contador declarado em um cabeçalho for está no escopo desse laço, mas não pode ser lido depois dele.
Estouro de pilha
Um estouro de pilha ocorre quando uma cadeia de chamadas de métodos precisa de mais espaço na pilha do que está disponível, produzindo StackOverflowError.
Chamadas que continuam adicionando registros sem deixá-los terminar podem acabar esgotando a pilha.
Extração de método
A extração de método move um trecho coerente de código para um método auxiliar, transformando entradas variáveis em parâmetros e resultados necessários em valores de retorno.
Extrair um laço de soma para sumUpTo(int n) deixa quem chama responsável pelo próprio texto do relatório.

I

Inicialização
A inicialização dá a uma variável seu valor inicial antes que o código posterior a leia ou atualize; variáveis locais não têm valor inicial automático.
Escrever int total = 0; antes de um laço de soma dá à primeira adição um total existente para atualizar.
Instrução inalcançável
Uma instrução inalcançável é código que Java determina não poder ser executado, como uma instrução diretamente após return no mesmo bloco.
Uma exibição diretamente após um return incondicional no mesmo bloco é rejeitada pelo compilador.
Instrução return
Uma instrução return encerra a chamada do método atual, devolvendo um valor em um método que não é void ou nenhum valor em um método void.
A instrução return minutes * 60; encerra o cálculo e fornece a quantidade de segundos.

J

Javadoc
Javadoc é documentação escrita em um comentário /** ... */ acima de uma declaração, com marcações que descrevem parâmetros e resultados.
Use @param minutes para explicar uma entrada e @return para descrever o texto formatado que ela produz.

L

Lista de parâmetros
Uma lista de parâmetros é a sequência ordenada de variáveis de entrada com tipos declarados entre os parênteses do cabeçalho de um método.
A lista (int width, int height) exige dois argumentos, associados primeiro a width e depois a height.

M

Método
Um método é um bloco nomeado de instruções que executa uma tarefa sempre que a execução do programa alcança uma chamada a ele.
Um método printHeader() pode exibir o mesmo título de relatório em vários lugares de um programa.
Método auxiliar
Um método auxiliar executa uma tarefa menor usada por outro método, tornando a operação maior mais fácil de ler e construir.
Um método de relatório pode chamar um formatador de duração em vez de realizar a formatação por conta própria.
Método com retorno booleano
Um método com retorno booleano retorna true ou false, geralmente para responder a uma pergunta que quem chama usa diretamente como condição.
Uma chamada como isEven(count) pode ser colocada diretamente entre os parênteses de uma instrução if.
Método estático
Um método estático pertence a uma classe e pode ser chamado sem criar um objeto dessa classe.
A chamada estática Math.abs(-6) usa o nome da classe Math e retorna o valor positivo 6.
Método privado
Um método privado só pode ser chamado por código de sua própria classe, mantendo um método auxiliar interno indisponível para outras classes.
Declarar um cálculo como private static permite que sua própria classe o use sem disponibilizar uma chamada externa.
Método provisório
Um método provisório é um método temporário com o cabeçalho planejado e um corpo mínimo que permite compilar o código ao redor ainda inacabado.
Um return 0; temporário pode servir de substituto enquanto o cálculo real é implementado e verificado.

P

Parâmetro
Um parâmetro é uma variável com tipo declarado no cabeçalho de um método que recebe um valor quando uma chamada específica começa.
Em printRepeated(String text, int times), text e times são os dois parâmetros declarados.
Passagem por valor
Passagem por valor significa que cada parâmetro recebe uma cópia do valor de seu argumento, portanto reatribuir o parâmetro deixa inalterada a variável de quem chamou.
Um método auxiliar pode aumentar seu parâmetro int enquanto o int original de quem chamou permanece inalterado.
Pilha de chamadas
A pilha de chamadas registra chamadas de métodos inacabadas, com a chamada mais recente sendo executada no topo enquanto quem a chamou aguarda abaixo.
Quando main chama um método auxiliar que chama outro método auxiliar, três registros podem estar na pilha ao mesmo tempo.
Projeto descendente
O projeto descendente começa pelo problema completo e divide repetidamente suas etapas em tarefas menores nomeadas ou chamadas de métodos.
Planeje chamadas de entrada, cálculo e relatório em main antes de preencher os corpos de seus métodos auxiliares.

R

Rastreamento da pilha
Um rastreamento da pilha é uma lista exibida dos registros de chamadas ativos no momento de um erro, mostrando nomes de métodos e locais na cadeia de chamadas.
O primeiro registro localiza a falha, e as linhas abaixo mostram quais métodos levaram até ela.
Refatoração
A refatoração altera a estrutura do código preservando seu comportamento, como ao substituir cálculos repetidos por chamadas.
Compare as mesmas entradas antes e depois da extração para verificar se os resultados e a saída permanecem iguais.
Referência
Uma referência é um valor que aponta para um objeto; copiar esse valor pode permitir que duas variáveis se refiram ao mesmo objeto.
Passar uma String copia sua referência para o parâmetro sem conectar as atribuições das duas variáveis.
Registro de ativação
Um registro de ativação contém os parâmetros e as variáveis locais de uma chamada e informações sobre onde quem chamou deve continuar depois.
Duas chamadas podem ter cada uma um parâmetro chamado minutes porque os parâmetros ocupam registros separados.
Resolução de sobrecarga
A resolução de sobrecarga é o processo pelo qual o compilador seleciona uma versão adequada de método a partir da quantidade e dos tipos dos argumentos de uma chamada.
Um argumento int escolhe uma sobrecarga int exata antes de uma versão que precisaria de conversão.
Retorno antecipado
Um retorno antecipado encerra um método antes do fim de seu corpo, geralmente após encontrar uma correspondência ou tratar uma condição de entrada.
Uma busca para assim que return candidate; é executado, mesmo que o laço tenha mais candidatos.

S

Sobrecarga
A sobrecarga define métodos com o mesmo nome e listas de parâmetros diferentes para que uma operação aceite diferentes formas de entrada.
Dois métodos chamados max podem aceitar dois valores int e três valores int, mantendo um único significado para o nome.
Sobrecarga com delegação
Uma sobrecarga com delegação chama outra versão da mesma operação, geralmente fornecendo um valor fixo para um argumento omitido.
Um método de exibição de linha com um argumento pode chamar a versão com dois argumentos usando um caractere de hífen fixo.
String imutável
Uma String imutável é uma String cujo conteúdo não pode ser alterado após sua criação; operações de texto podem produzir outra String.
Concatenar "!" e atribuir o resultado a um parâmetro String deixa inalterada a referência de quem chamou.

T

Tipo de retorno
Um tipo de retorno especifica o tipo de valor que um método fornece a quem o chama; void declara que ele não fornece valor.
Um método declarado como double average(int a, int b) promete um resultado double a quem o chama.

Ú

Último a entrar, primeiro a sair
Último a entrar, primeiro a sair é a ordem da pilha em que a chamada inacabada mais recente termina antes de quem a chamou e aguarda retomar a execução.
Um método auxiliar interno retorna antes que o método auxiliar externo possa terminar de usar esse valor retornado.

V

Valor de retorno
Um valor de retorno é o resultado que um método envia de volta ao ponto da chamada, onde pode ser armazenado ou usado em outra expressão.
Após int total = sum(6, 8);, o 14 retornado é armazenado na variável total de quem chamou.
Valor sentinela
Um valor sentinela é um resultado especial combinado para sinalizar uma condição, como uma busca que não encontra nenhum candidato correspondente.
Retornar -1 após uma busca pode sinalizar “não encontrado” quando -1 não pode ser uma correspondência válida.
Variável local
Uma variável local é declarada dentro de um método ou bloco e pertence à execução dessa região, não ao programa inteiro.
O total local em um método auxiliar é separado da variável local de outro método também chamada total.
void
A palavra-chave Java void declara que um método não retorna valor, mesmo que seu corpo execute ações como exibir conteúdo.
Uma chamada void a printTotal não pode preencher o lado direito de uma atribuição int apenas porque exibe um número.

Sobre esta aula

Por StudeliRelatar um erro

Crie seus próprios Materiais de Estudo

Transforme suas anotações, slides e documentos em Guias de Estudo, Questões de Prática, Flashcards e mais 6 ferramentas.

Começar