Skip to content

Commit 9395c15

Browse files
committed
feat(method-reference): regras e exemplos
Acrescentado regras e exemplos de Method Reference. Issue #22
1 parent a9cdbd0 commit 9395c15

File tree

7 files changed

+237
-0
lines changed

7 files changed

+237
-0
lines changed

book/04-lambda/sections/04-method-reference.asc

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,122 @@ Develop code that uses a method reference, including refactoring a lambda expres
1010
Desenvolver código que utiliza uma referência a método, incluindo a refatoração de uma expressão lambda para uma referência a método.
1111
--------------------------------------------------
1212

13+
A sintaxe de referência a um método é uma novidade do Java 8. Com ela é possível fazer referência a métodos específicos, em quatro ocasições diferentes:
14+
15+
* Referências a métodos estáticos -> `String::valueOf`
16+
* Referências a métodos de um objeto -> `instanciaDeString::isEmpty`
17+
* Referências a métodos de um tipo de objeto -> `String::isEmpty`
18+
* Referências a construtores -> `String::new`
19+
20+
A seguir serão apresentadas as ocasiões em que cada uma dessas referências é útil.
21+
22+
. Chamadas a métodos estáticos em expressões lambda podem virar uma referência ao método.
23+
+
24+
[source,java,indent=0]
25+
.{java-package}/methodreference/MethodReference_Static.java
26+
----
27+
include::{section-java-package}/methodreference/MethodReference_Static.java[tag=code]
28+
----
29+
+
30+
.Saída no console
31+
[source,console]
32+
----
33+
5
34+
5
35+
----
36+
+
37+
Essa utilização de _method reference_ só é possível porque:
38+
+
39+
* A implementação de `String.valueOf(int)` satisfaz a interface funcional `Function` (recebe um argumento e retorna um valor).
40+
* O argumento de entrada da expressão lambda `x` é exatamente o mesmo passado para o método `String.valueOf(x)`.
41+
* Essa é a única chamada que essa expressão lambda faz.
42+
43+
. Chamadas a métodos de uma instância também podem ser representados como uma referência a um método.
44+
+
45+
[source,java,indent=0]
46+
.{java-package}/methodreference/MethodReference_Instance.java
47+
----
48+
include::{section-java-package}/methodreference/MethodReference_Instance.java[tag=code]
49+
----
50+
+
51+
.Saída no console
52+
[source,console]
53+
----
54+
5 - 8
55+
5 - 8
56+
----
57+
+
58+
Essa utilização de _method reference_ só é possível porque:
59+
+
60+
* A implementação de `Conversor.converte(Integer, Integer)` satisfaz a interface funcional `BiFunction` (recebe dois argumentos e retorna um valor).
61+
* Os argumentos de entrada da expressão lambda `x` e `y` são exatamente os mesmos passados para o método `Conversor.converte(Integer, Integer)`.
62+
* Essa é a única chamada que essa expressão lambda faz.
63+
64+
. Chamadas a métodos de um tipo específico, sem especificar a instância, também podem ser representados como uma referência a um método.
65+
+
66+
[source,java,indent=0]
67+
.{java-package}/methodreference/MethodReference_Type.java
68+
----
69+
include::{section-java-package}/methodreference/MethodReference_Type.java[tag=code]
70+
----
71+
+
72+
.Saída no console
73+
[source,console]
74+
----
75+
8.0
76+
8.0
77+
----
78+
+
79+
Nesse exemplo, a referência está sendo feita ao método `doubleValue` do *tipo* `Integer`. Essa utilização de _method reference_ só é possível porque:
80+
+
81+
* Nossa expressão lambda satisfaz a interface funcional `Function` (recebe um argumento e retorna um valor).
82+
* A expressão lambda recebe um argumento `x` do tipo `Integer`, que possui o método `doubleValue` que não recebe parâmetros.
83+
* Essa é a única chamada que essa expressão lambda faz.
84+
85+
. Também é possível utilizar a referência ao método de um tipo, como no exemplo anterior, mesmo que o método receba parâmetros.
86+
+
87+
[source,java,indent=0]
88+
.{java-package}/methodreference/MethodReference_TypeWithParam.java
89+
----
90+
include::{section-java-package}/methodreference/MethodReference_TypeWithParam.java[tag=code]
91+
----
92+
+
93+
.Saída no console
94+
[source,console]
95+
----
96+
-1
97+
-1
98+
----
99+
+
100+
Nesse exemplo o compilador "descobre" ainda mais coisas que nos exemplos anteriores. Ao escrever apenas a referência ao método, ele entende que o primeiro argumento `x` será a instância de `Integer` onde o método `compareTo` será chamado. E também que o segundo argumento `y` é a instância de `Integer` que será passada como argumento para o método `compareTo`.
101+
102+
. Chamadas a um construtor também podem ser representadas como uma referência a um método.
103+
+
104+
[source,java,indent=0]
105+
.{java-package}/methodreference/MethodReference_Constructor.java
106+
----
107+
include::{section-java-package}/methodreference/MethodReference_Constructor.java[tag=code]
108+
----
109+
+
110+
.Saída no console
111+
[source,console]
112+
----
113+
1
114+
1
115+
----
116+
+
117+
Esse exemplo é muito parecido com o anterior, com a única diferença sendo que o método referenciado é um construtor. Perceba que o construtor também recebe um parâmetro e, assim como no exemplo anterior, o compilador entende que o argumento da função lambda deve ser passado para o construtor que foi chamado.
118+
119+
. Expressões lambda complexas não podem ser convertidas em referência a método, como a expressão abaixo:
120+
+
121+
[source,java,indent=0]
122+
.{java-package}/methodreference/MethodReference_Complex.java
123+
----
124+
include::{section-java-package}/methodreference/MethodReference_Complex.java[tag=code]
125+
----
126+
+
127+
Como nesse caso temos uma outra `String` `+ "2"` sendo acrescentada no construtor, não há como representar isso com uma simples referência ao construtor.
128+
13129
.Referências
14130
****
15131
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.j6toj8.lambda.methodreference;
2+
3+
import java.util.function.Function;
4+
5+
public class MethodReference_Complex {
6+
7+
public static void main(String[] args) {
8+
// tag::code[]
9+
Function<String, Integer> stringParaInteger1 = s -> new Integer(s + "2");
10+
System.out.println(stringParaInteger1.apply("1"));
11+
// end::code[]
12+
}
13+
14+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.j6toj8.lambda.methodreference;
2+
3+
import java.util.function.Function;
4+
5+
public class MethodReference_Constructor {
6+
7+
public static void main(String[] args) {
8+
// tag::code[]
9+
// representação com expressão lambda
10+
Function<String, Integer> stringParaInteger1 = s -> new Integer(s);
11+
// representação com referência ao construtor
12+
Function<String, Integer> stringParaInteger2 = Integer::new;
13+
14+
// os resultados serão iguais
15+
System.out.println(stringParaInteger1.apply("1"));
16+
System.out.println(stringParaInteger2.apply("1"));
17+
// end::code[]
18+
}
19+
20+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.j6toj8.lambda.methodreference;
2+
3+
import java.util.function.BiFunction;
4+
5+
public class MethodReference_Instance {
6+
7+
// tag::code[]
8+
static class Conversor {
9+
public String converte(Integer x, Integer y) {
10+
return String.valueOf(x) + " - " + String.valueOf(y);
11+
}
12+
}
13+
14+
public static void main(String[] args) {
15+
Conversor conversor = new Conversor(); // instância da classe Conversor
16+
17+
// representação com expressão lambda
18+
BiFunction<Integer, Integer, String> converte1 = (x, y) -> conversor.converte(x, y);
19+
// representação com referência ao método da instância
20+
BiFunction<Integer, Integer, String> converte2 = conversor::converte;
21+
22+
// os resultados serão iguais
23+
System.out.println(converte1.apply(5, 8));
24+
System.out.println(converte2.apply(5, 8));
25+
}
26+
// end::code[]
27+
28+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.j6toj8.lambda.methodreference;
2+
3+
import java.util.function.Function;
4+
5+
public class MethodReference_Static {
6+
7+
public static void main(String[] args) {
8+
// tag::code[]
9+
// representação com expressão lambda
10+
Function<Integer, String> converteIntEmStr1 = x -> String.valueOf(x);
11+
// representação com referência ao método
12+
Function<Integer, String> converteIntEmStr2 = String::valueOf;
13+
14+
System.out.println(converteIntEmStr1.apply(5));
15+
System.out.println(converteIntEmStr2.apply(5));
16+
// end::code[]
17+
}
18+
19+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.j6toj8.lambda.methodreference;
2+
3+
import java.util.function.Function;
4+
5+
public class MethodReference_Type {
6+
7+
public static void main(String[] args) {
8+
// tag::code[]
9+
// representação com expressão lambda
10+
Function<Integer, Double> intParaDouble1 = x -> x.doubleValue();
11+
// representação com referência ao método d
12+
Function<Integer, Double> intParaDouble2 = Integer::doubleValue;
13+
14+
// os resultados serão iguais
15+
System.out.println(intParaDouble1.apply(8));
16+
System.out.println(intParaDouble2.apply(8));
17+
// end::code[]
18+
}
19+
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.j6toj8.lambda.methodreference;
2+
3+
import java.util.function.BiFunction;
4+
5+
public class MethodReference_TypeWithParam {
6+
7+
public static void main(String[] args) {
8+
// tag::code[]
9+
// representação com expressão lambda
10+
BiFunction<Integer, Integer, Integer> comparador1 = (x, y) -> x.compareTo(y);
11+
// representação com referência ao método compareTo do tipo Integer (que recebe um parâmetro)
12+
BiFunction<Integer, Integer, Integer> comparador2 = Integer::compareTo;
13+
14+
// os resultados serão iguais
15+
System.out.println(comparador1.apply(1, 2));
16+
System.out.println(comparador2.apply(1, 2));
17+
// end::code[]
18+
}
19+
20+
}

0 commit comments

Comments
 (0)