Como funciona esse negócio de "Classe<Tipo>" Na linguagem java?

Eu tava aprendendo, e me deparei com o ArrayList. Como eu crio um desse? Como faço uma classe que usa esse “maior e menor”? Quais as utilidades? Qual a sintaxe?

Pesquise por generics

2 curtidas

Vlw, que legal.
Foi você quem curtiu seu próprio comentário? kkkk

Clique no número ao lado do coração que você vê quem curtiu. :slight_smile:

kkkkkkk

Vc perguntou sobre o ArrayList e no link abaixo vc pode ver o código fonte desta classe no Java 8:

https://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/util/ArrayList.java

Agora, sobre como criar um ArrayList e a utilidade dos Generics…

Um array de inteiros

Vamos começar implementando um array de inteiros:

public class MeuArrayDeInteiros {
  private int[] elementos = new int[10];
  private int quantidadeAtual = 0;

  void add(int valor) {
    this.elementos[this.quantidadeAtual] = valor;
    this.quantidadeAtual++;
  }

  int get(int posicao) {
    return this.elementos[posicao];
  }

  int length() {
    return this.quantidadeAtual;
  }

  public static void main(String... args) {
    MeuArrayDeInteiros arrayDeInteiros = new MeuArrayDeInteiros();

    arrayDeInteiros.add(123);
    arrayDeInteiros.add(456);
    arrayDeInteiros.add(789);

    for (int i = 0; i < arrayDeInteiros.length(); i++) {
      System.out.println(arrayDeInteiros.get(i));
    }
  }
}

Trata-se de uma implementação extremamente simples para fins didáticos apenas e
ela tem um grande problema: Esta classe só serve como um array de inteiros.

Se eu quiser ter um array de Strings, teria que criar uma outra classe semelhante a essa.

Se eu preciso de um array de inteiros e outro de Strings não haveria tanto problema,
mas e se eu quiser um array de Funcionarios ou um de GameObjects?

Dá dor de cabeça só de pensar na repetição de código.

Um array de Object

Mas há uma forma de evitar tanta repetição e reaproveitar a mesma classe para qualquer tipo de dado, veja:

public class MeuArrayDeObjetos {
  private Object[] elementos = new Object[10];
  private int quantidadeAtual = 0;

  void add(Object valor) {
    this.elementos[this.quantidadeAtual] = valor;
    this.quantidadeAtual++;
  }

  Object get(int posicao) {
    return this.elementos[posicao];
  }

  int length() {
    return this.quantidadeAtual;
  }

  public static void main(String... args) {
    MeuArrayDeObjetos arrayDeStrings = new MeuArrayDeObjetos();

    arrayDeStrings.add("Hello");
    arrayDeStrings.add("World");
    arrayDeStrings.add(123);
    arrayDeStrings.add(new Object() {
      @Override
      public String toString() {
        return "Um objeto qualquer";
      }
    });

    for (int i = 0; i < arrayDeStrings.length(); i++) {
      System.out.println(arrayDeStrings.get(i));
    }
  }
}

Como vc pode ver, mudando o tipo de elementos para Object eu posso colocar Strings, inteiros e qualquer outra coisa que eu queira.

Não preciso mais criar uma classe para cada tipo de dado, mas temos um novo problema: Eu posso acrescentar qualquer tipo de dado!

Viu como eu nomeei minha variável como arrayDeStrings, mas apenas os 2 primeiros itens adicionados são, de fato, Strings?

Nós tornamos nossa classe mais flexivel, mas perdemos uma das grandes vantagens do Java que é sua tipagem forte e abrimos brecha para possíveis bugs.

Um array genérico

Com Generics é possível obter o melhor dos 2 mundos:

  • Criar uma classe flexivel, permitindo que a usemos para armazenar qualquer tipo de dado
  • Uma classe fortemente tipada, permitindo que nós limitemos o tipo de dado que queremos em cada array
public class MeuArrayGenerico<Tipo> {
  @SuppressWarnings("unchecked")
  private Tipo[] elementos = (Tipo[]) new Object[10];
  private int quantidadeAtual = 0;

  void add(Tipo valor) {
    this.elementos[this.quantidadeAtual] = valor;
    this.quantidadeAtual++;
  }

  Tipo get(int posicao) {
    return this.elementos[posicao];
  }

  int length() {
    return this.quantidadeAtual;
  }

  public static void main(String... args) {
    MeuArrayGenerico<String> arrayDeStrings = new MeuArrayGenerico<>();
    arrayDeStrings.add("Hello");
    arrayDeStrings.add("World");

    for (int i = 0; i < arrayDeStrings.length(); i++) {
      System.out.println(arrayDeStrings.get(i));
    }

    MeuArrayGenerico<Integer> arrayDeInteiros = new MeuArrayGenerico<>();
    arrayDeInteiros.add(123);
    arrayDeInteiros.add(456);

    for (int i = 0; i < arrayDeInteiros.length(); i++) {
      System.out.println(arrayDeInteiros.get(i));
    }

    MeuArrayGenerico<Object> arrayDeObjects = new MeuArrayGenerico<>();
    arrayDeObjects.add("Hello");
    arrayDeObjects.add(123);
    arrayDeObjects.add(new Object() {
      @Override
      public String toString() {
        return "Um objeto qualquer";
      }
    });

    for (int i = 0; i < arrayDeObjects.length(); i++) {
      System.out.println(arrayDeObjects.get(i));
    }
  }
}

Acima eu criei 3 arrays diferentes:

  • O primeiro só pode conter Strings
  • O Segundo só pode conter inteiros
  • O terceiro pode conter qualquer tipo de dado

Agora obteremos um erro de compilação sempre que tentarmos inserir no nosso array um tipo de dado diferente daquele que foi definido durante sua criação

arrayDeStrings.add(123); // erro de compilação
arrayDeInteiros.add("Hello"); // erro de compilação

Conclusão

Como vc pode ver, Generics são um recurso poderemos que, entre outras coisas, nos permitem flexibilizar nossas classes sem perder a tipagem forte e sem repetição de código.

1 curtida

Isso será útil para pilhas ou filas, né kkk. Java é muito top

1 curtida