O operador de dois pontos em Java 8
1. Visão geral
Neste artigo rápido, discutiremosdouble colon operator (::) no Java 8 e examinaremos os cenários onde o operador pode ser usado.
Leitura adicional:
Perguntas da entrevista do Java 8 (+ respostas)
Um conjunto de perguntas populares da entrevista relacionadas ao Java8 e, é claro, respostas.
Novos recursos no Java 8
Uma breve introdução aos novos recursos do Java 8; o foco está nos métodos de interface estáticos e padrão, nas referências de método estático e em Opcional.
2. De Lambdas para Operador de Dois Pontos
Com expressões Lambdas, vimos que o código pode se tornar muito conciso.
Por exemplo, paracreate a comparator, a seguinte sintaxe é suficiente:
Comparator c = (Computer c1, Computer c2) -> c1.getAge().compareTo(c2.getAge());
Então, com inferência de tipo:
Comparator c = (c1, c2) -> c1.getAge().compareTo(c2.getAge());
Mas podemos tornar o código acima ainda mais expressivo e legível? Vamos dar uma olhada:
Comparator c = Comparator.comparing(Computer::getAge);
Usamos o operador:: como abreviação para lambdas chamando um método específico - por nome. E, no final, o resultado é, obviamente, uma sintaxe ainda mais legível.
3. Como funciona?
Simplificando, quando estamos usando uma referência de método - a referência de destino é colocada antes do delimitador::e o nome do método é fornecido depois dele.
Por exemplo:
Computer::getAge;
Estamos vendo uma referência de método para o métodogetAge definido na classeComputer.
Podemos então operar com essa função:
Function getAge = Computer::getAge;
Integer computerAge = getAge.apply(c1);
Observe que estamos referenciando a função - e, em seguida, aplicando-a ao tipo certo de argumento.
4. Referências de método
Podemos fazer bom uso desse operador em alguns cenários.
4.1. Um método estático
Primeiro, vamos fazer uso dea static utility method:
List inventory = Arrays.asList(
new Computer( 2015, "white", 35), new Computer(2009, "black", 65));
inventory.forEach(ComputerUtils::repair);
4.2. Um método de instância de um objeto existente
A seguir, vamos dar uma olhada em um cenário interessante -referencing a method of an existing object instance.
Vamos usar a variávelSystem.out - um objeto do tipoPrintStream que suporta o métodoprint:
Computer c1 = new Computer(2015, "white");
Computer c2 = new Computer(2009, "black");
Computer c3 = new Computer(2014, "black");
Arrays.asList(c1, c2, c3).forEach(System.out::print);
4.3. Um método de instância de um objeto arbitrário de um tipo específico
Computer c1 = new Computer(2015, "white", 100);
Computer c2 = new MacbookPro(2009, "black", 100);
List inventory = Arrays.asList(c1, c2);
inventory.forEach(Computer::turnOnPc);
Como você pode ver, estamos nos referindo ao métodoturnOnPc não em uma instância específica, mas no próprio tipo.
Na linha 4, o método de instânciaturnOnPc será chamado para cada objeto deinventory.
E isso naturalmente significa que - parac1, o métodoturnOnPc será chamado na instânciaComputer e parac2 na instânciaMacbookPro.
4.4. Um Super Método de um Objeto Particular
Suponha que você tenha o seguinte método na superclasseComputer:
public Double calculateValue(Double initialValue) {
return initialValue/1.50;
}
e este na subclasseMacbookPro:
@Override
public Double calculateValue(Double initialValue){
Function function = super::calculateValue;
Double pcValue = function.apply(initialValue);
return pcValue + (initialValue/10) ;
}
Uma chamada para o métodocalculateValue em uma instânciaMacbookPro:
macbookPro.calculateValue(999.99);
também produzirá uma chamada paracalculateValue na superclasseComputer.
5. Referências de construtor
5.1. Crie uma nova instância
Fazer referência a um construtor para instanciar um objeto pode ser bastante simples:
@FunctionalInterface
public interface InterfaceComputer {
Computer create();
}
InterfaceComputer c = Computer::new;
Computer computer = c.create();
E se você tiver dois parâmetros em um construtor?
BiFunction c4Function = Computer::new;
Computer c4 = c4Function.apply(2013, "white");
Se os parâmetros forem três ou mais, você deverá definir uma nova interface Funcional:
Em seguida, inicialize seu objeto:
TriFunction c6Function = Computer::new;
Computer c3 = c6Function.apply(2008, "black", 90);
5.2. Criar uma matriz
Finalmente, vamos ver como criar uma matriz de objetosComputer com cinco elementos:
Function computerCreator = Computer[]::new;
Computer[] computerArray = computerCreator.apply(5);
6. Conclusão
Como estamos começando a ver, o operador de dois pontos duplos - introduzido no Java 8 - será muito útil em alguns cenários e especialmente em conjunto com Streams.
Também é muito importante dar uma olhada nas interfaces funcionais para uma melhor compreensão do que acontece nos bastidores.
Osource code completo para o exemplo está disponível emthis GitHub project - este é um projeto Maven e Eclipse para que possa ser importado e usado como está.