Introdução à linguagem C, Operadores

Sejam bem vindos ao curso de introdução à linguagem de programação C, nesta aula iremos aprender sobre operadores.

Introdução à linguagem C, Variáveis

Sejam bem vindos ao curso de introdução à linguagem de programação C, nesta aula iremos aprender o que é variáveis.

Introdução à linguagem C, Introdução

Sejam bem-vindos ao curso de introdução à linguagem de programação C, nesta aula iremos ver um pouco da história do computador bem como sua evolução, além disso iremos aprender a montar o ambiente para iniciar a programar em C.

Java 8, Parte 4

Seja bem-vindo a quarta parte da série de tutorias sobre Java 8 e neste tutorial iremos entender o que é e para que serve os method references.

Sumário

  1. Seja bem vindo Lambda
  2. Interfaces funcionais
  3. Default Methods
  4. Method Reference

Method References

O method reference é um recurso bastante parecido com as expressões lambdas e também são inferidos em tempo de compilação, sua sintaxe é bastante simples, vamos a um exemplo:

public class Author {
	private String name;
	
	// construtor, gets e sets


	public void imprime() {
		System.out.println(name);
	}
}

Author caique = new Author("Caique Jhones");
Author junior = new Author("Junior dos Santos");
Author flavio = new Author("Flávio José");

List<Author> autores = Arrays.asList(caique, junior, flavio);

Consumer<Author> comLambda = a -> a.imprime();
Consumer<Author> comReference = Author::imprime;

autores.forEach(comLambda);
System.out.println("-------------");
autores.forEach(comReference);

A saída:

Caique Jhones
Junior dos Santos
Flávio José
-------------
Caique Jhones
Junior dos Santos
Flávio José

Perceba que foi utilizado o nome da classe juntamente com o delimitador :: concatenado com o nome do método sem os parênteses, isso equivale a expressão lambda só que com um código mais enxuto, esse novo conceito da linguagem será útil na utilização das novas API’s (como RxJava por exemplo) e deixará o código mais funcional. Não existe reflexão em method reference tudo é feito em tempo de compilação.

Referenciando métodos de instância

Um method reference do tipo Author::imprime só pode ser atribuído a uma interface funcional que receba como argumento uma instância da classe Author, que é o caso da interface Consumer:

public interface Consumer<T> {
    void accept(T t);
}

a partir daí o compilador pode executar o método imprime da instância recebida no método acept. Entretanto podemos utilizar uma instância de Author, o method reference fica desta forma: caique::imprime, e a partir daí utilizá-lo em uma interface funcional que não recebe nenhum parâmetro. Exemplo:

Runnable r = caique::imprime;
new Thread(r).start();

Não confunda a chamada Author::imprime com caique::imprime, pois o primeiro executará o método de qualquer Author que será passado por parâmetro dentro da interface funcional, já o segundo executará o método da instância que o chamou.

Com construtores

Podemos ainda referenciar os construtores para criarmos novas instâncias, como se fosse um factory, assim:

//Com construtor padrão

Supplier<Author> factory = Author::new;
Author semNome = factory.get();

//Com contrutor que recebe um argumento

Function<String, Author> fac = Author::new;
Author caique = fac.apply("Caique Jhones");

Para criarmos uma instância, passamos o method reference Author::new para uma interface funcional que será responsável por devolver a nova instância, no caso de um construtor padrão utilizamos a interface java.util.function.Supplier, para um construtor com um argumento podemos utilizar a interface java.util.function.Function e usamos o método apply passando o nosso parâmetro. Podemos ainda utilizar a interface java.util.function.BiFunction, para casos onde temos dois parâmetros, evidentemente a API não supre todos os casos possíveis, mas nada impede que nós mesmos criarmos as interfaces. Os arrays também não ficaram de fora, para usarmos o method reference utilizamos a sintaxe array[]::new, a novidade aqui é que ganha-se os colchetes, exemplo: float[]::new.

Além disso podemos ainda referenciar um métodos da classe mãe, com um super::nomeDoMetodo e métodos estáticos como Integer::parseInt. Vale salientar que para cada operação desta, deve-se ter uma interface funcional que será a referência, aqui vimos algumas, mas existem diversas outras como: java.util.function.ToIntFunction, java.util.function.ToIntBiFunction e outras variações dos tipos primitivos, que evitam o autoboxing para este tipos. Contudo na maioria dos casos não nos preocuparemos com isso, já que o method reference será passado como argumento em vários métodos.

Neste tutorial vimos uma parte importante do Java 8, a partir daqui poderemos compreender como funciona a nova API de Stream e todas as novas funcionalidades e vantagens que a API Collection implementou.

Java 8, Parte 3

Seja bem-vindo a terceira parte da série de tutorias sobre Java 8 e neste tutorial iremos entender o que é e para que serve os métodos default.

Sumário

  1. Seja bem vindo Lambda
  2. Interfaces funcionais
  3. Default Methods
  4. Method Reference

Default Methods

Vimos no tutorial Seja bem vindo Lambda o método forEach que está presente na interface Iterable, mas como este método funciona e por que códigos anteriores ao Java 8 não quebram com a inclusão deste novo método? Vamos analisá-lo:

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

Isso mesmo, agora podemos utilizar métodos com código dentro de interfaces e todas as classes que implementam estas interfaces terão obrigatoriamente esses novos métodos. Para criar um método default basta utilizar a palavra reservada default. Vamos analisar também a interface Consumer:

package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);

    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

Notamos que existe um default method, vamos ver o que ele faz:

public static void exemplo3() {
	Consumer<String> m1 = t -> System.out.println("Bem vindo:");
	Consumer<String> m2 = t -> System.out.println(t);

	List<String> list = Arrays.asList("Lambda", "Interfaces funcionais", "Default methods");

	list.forEach(m1.andThen(m2));
}

A saída será:

Bem vindo:
Lambda
Bem vindo:
Interfaces funcionais
Bem vindo:
Default methods

Bem útil né? A API Collections ganhou vários métodos default que aumenta consideravelmente as capacidades da API, dentre eles temos o removeIf e o replaceAll, muito úteis quando estamos trabalhando com listas.

public static void exemplo4() {
	ArrayList<String> list = new ArrayList<>();
	list.add("Lambda");
	list.add("Interfaces funcionais");
	list.add("Default methods");

	list.removeIf(s -> s.contains("i"));

	list.forEach(s -> System.out.println(s));
}

A saída será:

Lambda
Default methods

Apesar de podermos agora escrever métodos dentro de interfaces isso não representa que o Java passou a aceitar heranças múltiplas, pois ainda tem-se restrições ao utilizar os default methods, um deles é que não é possível utilizar variáveis de instância, já que interfaces não as possui.

Top