Operador :: (Double Colon) em Java 8: do iniciante ao profissional
\n\nVocê já escreveu código em Java 8 e viu uma construção estranha como System.out::println ou String::length? Parece mágica, não é? Na verdade, não é mágica, mas sim uma das ferramentas mais elegantes do Java moderno — o operador dois pontos duplos (também conhecido como double colon operator ou referência a método).
Neste artigo, vamos explorar o operador :: desde os fundamentos até técnicas avançadas. Você aprenderá a escrever código mais limpo, conciso e legível. Vamos lá!
O que é o operador :: e para que serve?
\n\nO operador :: (double colon) foi introduzido no Java 8 como açúcar sintático para expressões lambda. Se uma expressão lambda simplesmente chama um método existente, você pode substituí-la por uma referência a método. Isso torna o código mais curto e expressivo.
Compare você mesmo:
\n\n// Expressão lambda\nlist.forEach(s -> System.out.println(s));\n\n// Referência a método (operador ::)\nlist.forEach(System.out::println);\n\nA segunda opção não é apenas mais curta, mas já diz: "Para cada elemento, chame o método println de System.out". Beleza!
\n\nQuatro tipos de referências a métodos
\n\nNo Java 8, existem quatro tipos principais de method reference. Vamos analisar cada um com exemplos.
\n\n1. Referência a método estático
\n\nSintaxe: ClassName::staticMethodName
Exemplo: contagem de números pares em uma lista.
\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class StaticMethodReference {\n public static boolean isEven(Integer number) {\n return number % 2 == 0;\n }\n\n public static void main(String[] args) {\n List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);\n \n // Lambda\n long countLambda = numbers.stream()\n .filter(n -> StaticMethodReference.isEven(n))\n .count();\n \n // Referência a método estático\n long countRef = numbers.stream()\n .filter(StaticMethodReference::isEven)\n .count();\n \n System.out.println("Números pares: " + countRef); // 3\n }\n}\n\nObserve: não estamos chamando o método isEven — estamos apenas passando uma referência a ele. O próprio Java substituirá cada elemento da lista como argumento.
2. Referência a método de instância de um objeto específico
\n\nSintaxe: objectReference::instanceMethodName
Este tipo é usado quando você já tem um objeto específico e deseja chamar seu método.
\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class InstanceMethodReference {\n public static void main(String[] args) {\n List<String> names = Arrays.asList("Ana", "Bruno", "Carlos");\n \n // Criando um objeto StringBuilder\n StringBuilder sb = new StringBuilder("Nomes: ");\n \n // Lambda\n names.forEach(name -> sb.append(name).append(" "));\n \n // Referência a método de instância\n // (mas append retorna StringBuilder, então usamos lambda)\n // Já para System.out.println - é ideal:\n names.forEach(System.out::println);\n \n System.out.println(sb.toString()); // Nomes: Ana Bruno Carlos\n }\n}\n\nExemplo clássico — System.out::println. System.out é um objeto específico do tipo PrintStream, e println é seu método.
3. Referência a método de instância de um objeto arbitrário de um tipo específico
\n\nSintaxe: ClassName::instanceMethodName
Este tipo é frequentemente confundido com o anterior. Aqui não especificamos um objeto concreto — em vez disso, dizemos: "Pegue qualquer objeto desta classe e chame seu método".
\n\nBlogs
Book Recommendations
Leia também
Biblioteca e binário em Rust: como empacotar e não perder desempenho
Trabalho com bancos de dados em C++: PostgreSQL e MongoDB para iniciantes
Refatoração de código legado em TypeScript: guia passo a passo
Segurança de aplicações C#: top 10 vulnerabilidades na prática
Implantação de PHP no Kubernetes: guia básico na prática