W3docs

Parâmetros de Métodos Java

Passe valores para métodos Java por meio de parâmetros e entenda a diferença entre parâmetros e argumentos.

Parâmetros são as entradas que um método declara; argumentos são os valores que você fornece ao chamá-lo. O compilador verifica se os argumentos correspondem aos parâmetros por tipo e posição, e então os entrega ao método como variáveis locais que ele pode usar em seu corpo.

Este capítulo percorre essa transferência em detalhes — a sintaxe, os tipos que você pode passar e as regras que Java aplica para converter entre eles.

Declarando parâmetros

A lista de parâmetros de um método é uma sequência separada por vírgulas de pares Tipo nome:

public static void greet(String name, int times) {
  for (int i = 0; i < times; i++) {
    System.out.println("Hello, " + name);
  }
}

Um método pode declarar zero, um ou muitos parâmetros. Cada um precisa do seu próprio tipo — não há atalho como int a, b (isso seria int a seguido de b, o que não compila).

Chamando com argumentos

No local da chamada, você passa valores na mesma ordem em que os parâmetros são declarados:

greet("Ada", 3);    // name = "Ada", times = 3

O compilador verifica duas coisas:

  1. Aridade — o número de argumentos corresponde ao número de parâmetros.
  2. Tipos — o tipo de cada argumento é compatível com o tipo do parâmetro correspondente.

Se alguma verificação falhar, seu programa não compilará. Passar uma String onde um int é esperado resultará em um erro como incompatible types: String cannot be converted to int.

Parâmetros são variáveis locais

Dentro do método, cada parâmetro se comporta como uma variável local inicializada com o valor do argumento:

public static int doubleIt(int n) {
  n = n * 2;          // legal: n is just a local
  return n;
}

int x = 5;
int result = doubleIt(x);   // result is 10
System.out.println(x);       // still 5

Reatribuir n dentro de doubleIt não afeta x no local da chamada. Cada chamada recebe sua própria cópia nova do parâmetro. É isso que as pessoas querem dizer quando dizem que Java é "passagem por valor" — cada argumento é copiado para o slot do parâmetro. Os próximos capítulos cobrem as implicações, especialmente para argumentos de objeto.

Informação
Java é sempre passagem por valor, mesmo para objetos. Com um tipo de referência, o valor que é copiado é a referência, não o objeto — portanto, o método pode mutar o objeto para o qual a referência aponta, mas reatribuir o parâmetro ainda não altera a variável do chamador. O capítulo passagem por valor explica isso em detalhes.

Alargamento implícito

Java alargará automaticamente um tipo numérico menor para um maior para corresponder ao parâmetro:

public static double half(double x) {
  return x / 2;
}

int n = 7;
double result = half(n);   // n is widened from int to double

O alargamento é permitido porque nenhuma informação é perdida. O estreitamento não é implícito — passar um double para um parâmetro int requer uma conversão explícita:

half(7.5);            // fine: double argument, double parameter
double d = 3.7;
int i = (int) d;      // explicit cast
half(i);              // also fine

As mesmas regras de alargamento se aplicam como na atribuição: byte → short → int → long → float → double, e char → int.

Parâmetros de objeto

Você pode passar qualquer objeto — String, um array, uma classe personalizada — declarando um parâmetro do tipo de referência correspondente:

public static int firstLength(String[] words) {
  if (words.length == 0) return 0;
  return words[0].length();
}

String[] colors = {"red", "green", "blue"};
System.out.println(firstLength(colors));   // 3

O argumento também pode ser null, caso em que o parâmetro é null e qualquer acesso a campo ou chamada de método sobre ele lança NullPointerException. Métodos que aceitam referências geralmente verificam primeiro ou documentam que null não é permitido.

Passando null

null é compatível com todo tipo de referência para atribuição, portanto você pode passá-lo para qualquer parâmetro de objeto:

greet(null, 1);

Se o método desreferenciar o parâmetro (name.length(), name.charAt(0), …), ele lança uma exceção. Um método defensivo trata null explicitamente, geralmente com uma verificação no início:

public static void greet(String name, int times) {
  if (name == null) name = "stranger";
  for (int i = 0; i < times; i++) {
    System.out.println("Hello, " + name);
  }
}

Parâmetros final

Você pode marcar um parâmetro como final para proibir reatribuição dentro do método:

public static int doubleIt(final int n) {
  // n = n * 2;     // ERROR: cannot assign a value to final variable n
  return n * 2;
}

Isso não muda o que o chamador vê — apenas se o corpo tem permissão de reutilizar o slot do parâmetro. Muitos guias de estilo tratam todos os parâmetros como se fossem final, mesmo sem a palavra-chave; basta calcular novos valores em vez de mutar o parâmetro.

Ordem de avaliação dos argumentos

Quando você escreve f(a(), b(), c()), os argumentos são avaliados da esquerda para a direita, todos antes de f ser chamado. Se a() lançar uma exceção, b() e c() nunca são executados.

public static int log(String label, int value) {
  System.out.println(label + " = " + value);
  return value;
}

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

sum(log("a", 1), log("b", 2), log("c", 3));
// prints:
//   a = 1
//   b = 2
//   c = 3

Esse determinismo é diferente de C e C++; em Java a ordem é fixa e previsível.

Um exemplo prático

java— editable, runs on the server

O que vem a seguir

Você sabe como os dados entram em um método. Às vezes, você quer dois métodos com o mesmo nome mas entradas diferentes — por exemplo, um que aceita um int e outro que aceita uma String. Java permite escrever ambos de uma vez com sobrecarga de métodos.

Prática

Prática
O que acontece com uma variável primitiva quando ela é passada como argumento para um método?
O que acontece com uma variável primitiva quando ela é passada como argumento para um método?
Was this page helpful?