hola a todos, tengo la siguiente duda y es con respecto ala utilizacion de <T>
siempre he utilizado es el object y estoy tratando de entender las ventajas de los genericos, 
ya se que sirve para asegurarse de tener listas homogéneas y así ahorrase el cast ala salida y ayuda a evitar errores...entre otras cosas... 
pero no estoy seguro que mas utilidad tenga, y no tengo muy claro donde es que es util utilizarla . 
Una clase para crear y realizar diferentes acciones con arboles que utilizaba Object la cambie a ese tipo generico quedando asi:  
/**    
Código:
 * @version 1.00 2010/4/1
 *////arbol binario de busqueda
public abstract class CArbolBB <T>{
	
	// atributos del arbol binario
	protected CNodo raiz=null;// raiz del arbol binario
	//Nodo de un arbol binario
	private class CNodo
	{
	private T datos;
	private CNodo izquierdo;
	private CNodo derecho;
	public CNodo(){}
	}
	
	//Posibles errores que se pueden dar relativos a un nodo
	public static final int CORRECTO = 000;
	public static final int NO_DATOS = 100;
	public static final int YA_EXISTE = 101;
	public static final int NO_EXISTE = 102;
    public CArbolBB() {}
    
    // metodo para redefinir, comaparando por el atributo que necesitemos
    public abstract int comparar(T obj1,T obj2);
    //metodo para redifinir, realizar con el nodo visitado
     public abstract void procesar(T obj);
     //metodo redefinir de tal forma que invoque a inorden con los argumentos deseados
      public abstract void visitarInorden();
      
      public T buscar(T obj)
      {
      // El método buscar permite acceder a un determinado nodo.
       CNodo actual = raiz; 
       int nComp = 0;
       // Buscar un nodo que tenga asociados los datos dados por obj
         while( actual != null )
         {
         if(( nComp = comparar( obj, actual.datos ))== 0)
         return( actual.datos );   // CORRECTO (nodo encontrado)
            else if ( nComp < 0 )	// buscar en el subárbol izquierdo
            actual = actual.izquierdo;
                else	// buscar en el subárbol derecho
          actual = actual.derecho;
         }
       return null; // NO.EXISTE
      }
   public int insertar(T obj)
      {
      	// El método insertar permite añadir un nodo que aún no está
      	 // en el árbol.
     CNodo ultimo = null, actual = raiz;
     int nComp = 0;
      if( obj == null ) return NO_DATOS;
      // Comienza la búsqueda para verificar si ya hay un nodo con
      // estos datos en el árbol
      while (actual != null)
       {
        if ((nComp = comparar( obj, actual .datos ))== 0)
         break; // se encontró el nodo
         else
         {
         ultimo = actual;
        if( nComp < 0 )   // buscar en el subárbol izquierdo
         actual = actual.izquierdo;
         else	// buscar en el subárbol derecho
         actual = actual.derecho;
         }
       }
if ( actual == null ) // no se encontró el nodo, añadirlo
{
CNodo nuevoNodo = new CNodo();
 nuevoNodo.datos = obj;
nuevoNodo.izquierdo = nuevoNodo.derecho = null;
// El nodo a añadir pasará a ser la raíz del árbol total si
// éste está vacio, del subárbol izquierdo de "último" si la
// comparación fue menor, o del subárbol derecho de "último" si
// la comparación fue mayor.
if ( ultimo == null  ) // árbol vacio
raiz = nuevoNodo;
 else if ( nComp < 0 )
ultimo.izquierdo = nuevoNodo;
 else
ultimo.derecho = nuevoNodo;
return CORRECTO;
} // fin del bloque if ( actual = null )
 else // el nodo ya existe en el árbol
return YA_EXISTE;
  }
      
public T borrar(T obj){
      
  // El método borrar permite eliminar un nodo del árbol. 
  CNodo ultimo = null, actual = raiz;
  CNodo marcado = null, sucesor = null;
  int nAnteriorComp = 0, nComp = 0;
if (obj == null) return null; // N0_DAT0S
// Comienza la búsqueda para verificar si hay un nodo con 
// estos datos en el árbol.
 while( actual != null )
 {
   nAnteriorComp = nComp; // resultado de la comparación anterior
  if (( nComp = comparar( obj, actual.datos )) == 0)
  break; // se encontró el nodo
  else
  {
   ultimo = actual ;
   if ( nComp < 0 )   // buscar en el subárbol izquierdo
   actual = actual.izquierdo;
   else	// buscar en el subárbol derecho
   actual = actual.derecho;
  }
} // fin del bloque whlle ( actual !- nuil )
if ( actual != null ){ // se encontró el nodo
      marcado = actual ;
      if (( actual.izquierdo == null && actual.derecho == null ))
       // se trata de un nodo terminal  (no tiene descendientes)
       sucesor = null;
        else if ( actual.izquierdo == null ) // nodo sin subárbol izq.
             sucesor = actual.derecho;
             else if ( actual.derecho == null ) // nodo sin subárbol derecho
                  sucesor = actual.izquierdo;
                   else   // nodo con subárbol izquierdo y derecho
                   {
                   // Referencia del subárbol derecho del nodo a borrar
                   sucesor = actual = actual.derecho;
                   // Descender al nodo más a la izquierda en el subárbol
                   // derecho de este nodo (el de valor más pequeño) y hacer
                   // que el subárbol izquierdo del nodo a borrar sea ahora
                   // el subárbol izquierdo de este nodo.
                     while ( actual.izquierdo != null )
                     actual = actual.izquierdo;
                     actual.izquierdo = marcado.izquierdo;
                   }
// Eliminar el nodo y rehacer los enlaces
      if ( ultimo != null )
      {
        if( nAnteriorComp < 0 )
         ultimo.izquierdo = sucesor;
         else
         ultimo.derecho = sucesor;
      }
      else
        raiz = sucesor;
        return marcado.datos; // CORRECTO
        // "marcado" será enviado a la basura
 }
 else // el nodo buscado no está en el árbol
 return null; // NO_EXISTE
}
	
      	
      
      
      public void inorden(CNodo r, boolean nodoRaiz)
      {
      	//orden de visita: subarbol izquierdo, raiz y subarbol derecho
      	CNodo actual = null;
      	if(nodoRaiz)
      	actual = raiz;// partir de la raiz
      	else
      	actual = r; // partir de un nodo cualquiera
      	if(actual != null)
      	{
      	inorden(actual.izquierdo,false);	// visitar subarbol izquierdo
        procesar(actual.datos);	//procesar los datos del nodo visitado
      	inorden(actual.derecho, false);//visitar subarbol derecho
      	}		
      			
      }
    
}
  si es necesario utilizar genericos aqui? 
otra duda me resulto cuando fui a redefinir los metodos abstractos en una subclase y no pude utilizar la misma T  asi:  
Código:
 public abstract class Redefinir_CArbolBB_para_Nota extends CArbolBB{
 public int comparar(Object obj1,Object obj2){
 if(((objetoNota)(obj1)).ObtenerNota()==((objetoNota)(obj2)).ObtenerNota())
 return 0;
 else if(((objetoNota)(obj1)).ObtenerNota()<((objetoNota)(obj2)).ObtenerNota())
       return -1;
       else
       return 1;
            
 }
 
    public void procesar(Object obj){
	System.out.println("Nombre estudiante "+((objetoNota)(obj)).ObtenerNombre());
	System.out.println("Curso estudiante "+((objetoNota)(obj)).ObtenerCurso());
	System.out.println("Nota estudiante "+((objetoNota)(obj)).ObtenerNota());
	}	
     //metodo redefinir de tal forma que invoque a inorden con los argumentos deseados
      public void visitarInorden(){
		  inorden(null,true);
	  }
}
  como ven tuve que volver a utilizar Object por que no puedo utilizar genéricos
¿por que no se puede?  
y la otra duda fue cuando en la clase principal voy hacer la declaración para que el árbol sea homogéneo asi:    
Código:
 public class Nota{
  public static void main(String arg[]){
   Redefinir_CArbolBB_para_Nota<objetoNota> Arbol=new Redefinir_CArbolBB_para_Nota<objetoNota>();
   objetoNota obj[]=new objetoNota[6];
    for(int i=0;i<6;i++){
	System.out.print("Nombre estudiante "+(i+1)+": ");	
	String N=Leer.leercadena();
	System.out.print("Curso estudiante "+(i+1)+": ");	
	int C=Leer.leerint();
	System.out.print("Nota estudiante "+(i+1)+": ");	
	double NO=Leer.leerint();
	obj[i]=new objetoNota(N,NO,C);
	Arbol.insertar(obj[i]);
	}
	Arbol.visitarInorden();
    	  
  }
  
    
}
  me marca error en la declaración  del objeto: "Redefinir_CArbolBB_para_Nota" 
bueno me surgen muchas preguntas: 
¿tiene que ver que el objeto sea de la subclase del árbol binario?
¿los genéricos solo sirven para las listas lineales ?
¿o solo funcionan con ciertas clases que vienen con java?
¿si estoy entendiendo bien la utilidad de los genéricos o estoy bien perdido? 
Agradezco al que me ayude con estas dudas...