Why was the parameterized class attribute T not instantiated?

7

I have this class that implements the IDAO interface

package DAO;
import java.util.ArrayList;


public class BdApp<T> implements IDAO<T> {

ArrayList<T> lst = new ArrayList<T>(); 
//ArrayList<Administrador> lstAdministrador = new ArrayList<Administrador>();
@Override
public void add(T c) {
    lst.add(c);
}


@Override
public void update(T o) {
    // TODO Auto-generated method stub

}


@Override
public ArrayList<T> listar() {
    // TODO Auto-generated method stub
    return lst;
}
}

And this class that raised my doubt:

package UI;

import java.util.ArrayList;
import java.util.Scanner;

import DTO.Contato;
import DAO.BdApp;

public class Menu {

private BdApp<Contato> bd;

public Menu(BdApp bd){
    this.bd = bd; 
}

public void cadContato(){
    Scanner sc = new Scanner(System.in);
    Contato contato = new Contato();
    System.out.print("Digite o nome: ");
    contato.setNome(sc.next());
    System.out.print("Digite o cpf: ");
    contato.setCpf(sc.next());

    bd.add(contato);
}

public void listarContatos(){
    ArrayList<Contato> lista = bd.listar();
    for (Contato contato : lista) {
        System.out.println(contato.getNome());
    }
}   
}

In this part:

private BdApp<Contato> bd;

Why he did not instantiate soon doing so:

  private BdApp<Contato> bd = new BdApp<Contato>(); ?

And if it were not for the parameterized class would the composition look like this?

 private BdApp bd;
    
asked by anonymous 11.02.2016 / 00:31

3 answers

6

In short I would define it as follows: badly done class project :), the constructor argument of Menu should also be typed, since BdApp is a raw type , which could be a reference to IDAO , not BdApp . >

  

Why did not he instantiate soon doing so: private BdApp<Contato> bd = new BdApp<Contato>(); ?

As this code is, it really does not make much difference in initializing the declaration or constructor, one way or another in the end it will only make sense to assign BdApp<Contato> or attribute bd to Menu not depend in anything generic (which leads us to think that it did not have to be generic). For example:

final BdApp<Integer> bd = new BdApp<>();
final Menu menu = new Menu(bd);
menu.listar();

This example compiles and runs smoothly, but it does not make sense to how the class project is. As it stands, the attribute is typed ( private BdApp<Contato> bd ), so even when building an instance of Menu I tried to change the type of the generic could have problems, as it was later used in the code. p>

In addition, the advantage of having assignment by constructor, setter , etc. is that the instance defines the concrete type, to be able to exchange implementations, to change implementation in runtime (with setter , for example), etc.

However this is quite common, see the example below:

  • abstract class Menu :
public abstract class Menu<T> {

    private final IDAO<T> bd;

    public Menu(final IDAO<T> bd) {
        this.bd = bd;
    }

    public void cadastrar() {
        try(final Scanner sc = new Scanner(System.in)) {
            bd.add(this.instance(sc));
        }
    }

    protected abstract T instance(final Scanner sc);

    public void listar() {
        final List<T> lista = bd.listar();
        for (final T t : lista) {
            this.imprimir(t);;
        }
    }

    protected abstract void imprimir(final T t);

}
  • class MenuContato :
public class MenuContato extends Menu<Contato> {

    public MenuContato(final IDAO<Contato> bd) {
        super(bd);
    }

    @Override
    protected Contato instance(final Scanner sc) {
        final Contato contato = new Contato();
        System.out.print("Digite o nome: ");
        contato.setNome(sc.next());
        System.out.print("Digite o cpf: ");
        contato.setCpf(sc.next());
        return contato;
    }

    @Override
    protected void imprimir(final Contato t) {
        System.out.println(t.getNome());
    }

}

See that we make Menu generic as well, so we could have Menu anything. In addition to this (and one of the better parts of this) is that we can change the implementation of IDAO , as stated above. That is, we can pass an instance that saves the data in a list, one that uses persistence in BD, etc., without having to change anything at all.

  

And if it were not for the parameterized class would the composition look like this?

Yes, if it is not a generic type, it would not be able to parameterize it, so it would be as you observed it, only private BdApp bd ;

Probably this code is not yours, but follow some observations, in addition to the points previously mentioned:

  • Always consider having the reference not for the concrete type, but for the interface, this gives you more flexibility. That is, private BdApp<Contato> bd = new BdApp<>(); instead of private BdApp<Contato> bd = new BdApp<Contato>(); , private List<T> lst = new ArrayList<>(); instead of ArrayList<T> lst = new ArrayList<T>(); and so on. See more ;
  • from Java 7 there is diamond operator , then you do not need to qualify the concrete type when instantiating the object, it will be inferred by the reference, ie private List<T> lst = new ArrayList<>(); and not private List<T> lst = new ArrayList<T>(); ;

I quoted a smells of the code just to notice how much it looks like it's in trouble = )

    
11.02.2016 / 01:18
6

If the class was not parameterized, it would still be the same.

Ideally, the constructor method parameter type should be of the same type as the member it will initialize, that is, it should be parameterized as well.

Normally it is left to initialize in the member when the initialization should happen in the constructor, which is exactly what was done. You do not have to boot twice. Direct initialization of the member would be lost before it was used.

    
11.02.2016 / 01:10
1

It is simply separation of responsibilities. Project decision only. "Injecting" dependencies in this way is useful for facilitating testing, among other things.

If the class was not parameterized, all <AlgumTipo> would disappear.

If your question is about why the constructor parameter has no specified type within <> , the answer is omission - probably lack of attention or knowledge. The compiler accepts this sort of thing, even though it generates an alert. If you do not decide a type there, anything is going to come in, which compromises the security of your application types, basically destroying the purpose of using generics .     

11.02.2016 / 00:40