J2SE1.5 1.5 Generics

6 respostas
Luiz_Cesar_dos_Santo
class A <E>

{}

class B <?>

{}

class C

{

public boolean f (A<Integer> a ) {}

public boolean f (A<String> a ) {}

public boolean f (B<String> a ) {}

public boolean f (Vector<a><String>>a ) {}

public boolean f (Vector<b><String>>a ) {}

}</b></a>

O que seria equivalente em C++?

6 Respostas

T
import java.util.Vector;

class A &lt;E&gt; {
}

class B &lt;E&gt; { // B<?>  erro de compilação
}

class C
{
    public boolean f (A&lt;Integer&gt; a ) {
        return false;
    }
    public boolean f (A&lt;String&gt; a ) { // erro de compilação pois bate com A&lt;Integer&gt;
        return false;
    }
    public boolean f (B&lt;String&gt; a ) {
        return false;
    }
    public boolean f (Vector< A &lt;String&gt; >a ) {
        return false;
    }
    public boolean f (Vector< B &lt;String&gt; >a ) { // erro de compilação pois bate com Vector < A < String > > a
        return false;
    }
}

Corrigi um pouco seu exemplo, mas ainda dá erros de compilação nas linhas indicadas.

Na verdade em C++ o conceito de templates é um pouco diferente do de generics (em C++ os templates instanciam uma nova classe, em Java o generics efetua ‘erasure’), mas exceto pelo caso de que não existe em C++ o ‘wildcard’ ou ‘?’, poderíamos ter algo como:

Java: String --> C++: std::string
Java: Integer --> C++: int ( não existe algo como um ‘wrapping’)
Java: Vector --> C++: std::vector

Em C++ o programa semelhante, mas sem erros de compilação e com semântica um pouco diferente, é :

#include &lt;vector&gt;
#include &lt;string&gt;
using namespace std;


template&lt;class E&gt; class A {
};

template&lt;class E&gt; class B { // B<?> dá erro de compilação
};

class C
{
public:
    bool f (A&lt;int&gt; a ) { //1
        return false;
    }
    bool f (A&lt;string&gt; a ) { //2
        return false;
    }
    bool f (B&lt;string&gt; a ) { //3
        return false;
    }
    bool f (vector< A &lt;string&gt; >a ) { //4
        return false;
    }
    bool f (vector< B &lt;string&gt; >a ) { //5
        return false;
    }
}; 

main () {
    C c;
    A&lt;int&gt; aint; A&lt;string&gt; astring; B&lt;string&gt; bstring; 
    vector< A&lt;string&gt; > vastring;
    vector< B&lt;string&gt; > vbstring;
    c.f (aint); // 1
    c.f (astring); // 2
    c.f (bstring); // 3
    c.f (vastring); // 4
    c.f (vbstring); // 5
}
Luiz_Cesar_dos_Santo

Certo, vlw, entendi a sobrecarga feita e quais eram os erros, mas quais são as implicações no uso de generics em java para a performance do programa diferentemente de C++?

T

Os generics em Java não foram feitos para tornar seu programa mais rápido ou mais eficiente: eles foram feitos para resolver um outro problema, que é o uso de ‘casts’ excessivo e indevido que pode ocorrer sem generics. Você poderia chamar o recurso de ‘autocasting’.
Por exemplo, para ter um ArrayList de String, você escreveria:

List l = new ArrayList(); // aqui não há nada que indique que a sua intenção 
// é construir uma lista que só contém strings.
l.add ("str1");
l.add ("str2");
String s = (String) l.get(0); // aqui você está chutando que há uma String 
// na primeira posição da lista. 
// Se não houver, você vai ter um ClassCastException.

Agora, como você deve saber melhor que eu, você só precisa escrever:

List< String >  l = new ArrayList < String > (); // aqui você diz
// claramente que quer construir uma lista que  contém strings.
l.add ("str1");
l.add ("str2");
String s = l.get(0); // Você sabe que  uma String na primeira posição da lista.

Só que devido ao fenômeno de ‘erasure’, o código “generics” escrito acima é exatamente igual, em termos de runtime, ao código anterior, incluindo o cast para String que não aparece mais explicitamente no código com ‘generics’.

Parece um pouco de perfumaria, mas você irá ver na prática que o recurso de Generics torna seu código mais claro em alguns pontos (é claro que você normalmente não vai precisar de declarar uma rotina tal como java.util.Collections.max(), cuja declaração é public static < T extends Object & Comparable< ? super T > > T max (Collection < ? extends T > coll) )

pcalcado

thingol:
Os generics em Java não foram feitos para tornar seu programa mais rápido ou mais eficiente: eles foram feitos para resolver um outro problema, que é o uso de ‘casts’ excessivo e indevido que pode ocorrer sem generics. Você poderia chamar o recurso de ‘autocasting’.

…e para solucionar (gambiarralmente) o problema de covariância, que acotnece quando você rpecisa que o tipo de retorno de um método varie com o tipo do parâmetro passado, algum atributo ou coisa do tipo.

[]s

louds

Phillip, de que raios voce está falando? O java 5 suporta covariancia de retorno para métodos sobrescritos. Coisa que existe no c++ e fazia uma boa falta no java.
Exemplo:

class A{
  public Collection x() { return null; }
}

class B extends A{
  public ArrayList x() { return null; }
}
pcalcado

Louds,

A Covariância pode ser resolvida de várias formas, ams se você não tem tipagem dinâmica como em Templates/Generics nem tipos ancorados, você não pode resolver o preblema do tipo:

class  Bla&lt;T&gt;{
private T e;

public T getE(){
 return e;
}


}

ou

T public doBlablabla(&lt;T&gt; argumento);

A sobrescrita de tipo de retorno é ótima, mas não resolve por si só o problema.

[]s

Criado 17 de março de 2005
Ultima resposta 17 de mar. de 2005
Respostas 6
Participantes 4