Red de conocimiento informático - Aprendizaje de programación - Genéricos de Java y .

Genéricos de Java y .

La diferencia entre los tipos genéricos y

y contienen nuevos conceptos en JAVA 5.0. Su apariencia ha provocado que muchas personas malinterpreten su propósito:

1.

extiende T>En primer lugar, es fácil malinterpretarlo como una colección de todas las clases que heredan de T. Esto está muy mal. Creo que si puedes seguir leyendo, debes haber visto o usado List

extiende T>, ¿verdad? ¿Por qué digo que está mal entenderlo como un conjunto? Si se entiende como una colección, ¿por qué no utilizar List? Entonces

extiende

T> no es un conjunto, se refiere a alguna subclase de T. Recuerde, es de un solo tipo, el problema es que ni siquiera está seguro de cuál es, lo que introduce incertidumbre, por lo que no se pueden agregar elementos mediante

add() . Quizás también estés pensando, ¿por qué add(T) es inútil? Debido a que

T> es una subclase de T, es posible que un contenedor que se puede colocar en una subclase no se pueda colocar en una superclase, lo que significa que no se puede colocar en T.

2. es más fácil de usar aquí. No tiene tantas restricciones como . Lo que significa aquí es que la clase T sirve como el límite inferior de un determinado. clase. En resumen, es T La superclase de una clase. Pero, ¿por qué funciona add(T)? Debido a que un contenedor que puede cargar una determinada clase debe poder cargar sus subclases, este es el concepto de polimorfismo.

Borrado

Además

Probablemente el aspecto más desafiante de los genéricos es el borrado, que se implementa en el lenguaje Java

Tecnología básica de genéricos. Borrar significa que el compilador básicamente descarta mucha información de tipo para una clase parametrizada cuando genera el archivo de clase. El compilador genera código a través de conversiones, tal como los programadores generaban código a mano antes de la llegada de los genéricos

. La diferencia es que el compilador ha verificado una gran cantidad de restricciones de seguridad de tipos al principio y, sin una generalización, el compilador no verificaría estas restricciones.

Implementar una implicación genérica mediante el borrado es muy importante y puede resultar confuso a primera vista. Aunque no puede asignar una Lista a una Lista porque son tipos diferentes, las variables de tipo List y las variables de tipo List pertenecen a la misma clase. Para entender esto, evalúe el siguiente código:

new List().getClass() == new List().getClass()

Compilador Generar solo una clase para List. Cuando se genera el código de bytes para una Lista, habrá muy pocos rastros de sus parámetros de tipo.

Al generar código de bytes para una clase genérica,

el compilador reemplazará los parámetros de tipo eliminándolos. Para parámetros de tipo sin restricciones (), el valor de borrado es

Objeto. Para un parámetro de tipo restringido (>), su valor borrado es su límite superior (

Comparable en este caso). Para parámetros de tipo con límites múltiples, se utiliza el valor de borrado de su límite más a la izquierda.

Si inspecciona el código de bytes generado, no podrá distinguir el código de List y List.

En el código de bytes, la restricción de tipo T se reemplaza por un límite superior en T (generalmente Objeto).

Múltiples restricciones

Un parámetro de tipo puede tener múltiples restricciones. Esto es útil cuando desea restringir un parámetro de tipo (por ejemplo, para que sea comparable y serializable). La sintaxis para restricciones múltiples es separar las restricciones con el símbolo "con":

clase C&Serializable>

El tipo comodín puede tener un límite - un límite superior o un límite inferior. Los parámetros de tipo especificados pueden tener uno o más límites superiores. Se puede utilizar un parámetro de tipo con múltiples restricciones para acceder a métodos y campos para cada una de sus restricciones.

Parámetros de tipo y argumentos de tipo

En la definición de una clase parametrizada, el nombre del marcador de posición (como la V en Colección) se denomina tipo

Parámetros, que son similares a los parámetros formales en las definiciones de métodos. En una declaración de variable de una clase parametrizada, el valor de tipo especificado en la declaración se denomina parámetro de tipo, que es análogo a los parámetros reales en una llamada a un método. Pero en aplicaciones prácticas, generalmente se les llama "parámetros de tipo". Por lo tanto la definición es la siguiente:

Interface Collection { ...}

y la declaración:

Collection cs = new HashSet ( );

Entonces el nombre V (que se puede utilizar en todo el cuerpo de la interfaz de la Colección) se denomina parámetro formal de tipo. Ambos usos de String en la declaración cs son argumentos de tipo (uno para Collection y otro para HashSet).

Existen algunas restricciones al utilizar parámetros formales de tipo

. En la mayoría de los casos, los parámetros de tipo se pueden utilizar en cualquier lugar donde se pueda utilizar una definición de tipo real. Pero hay excepciones. No puedes usarlos para crear objetos o matrices,

ni en un contexto estático o en un contexto que maneje excepciones. Tampoco se pueden utilizar como supertipos (clase Foo extends

T), expresiones de instancia o constantes de clase.

Del mismo modo, existen algunas restricciones sobre qué tipos se pueden utilizar como argumentos de tipo. Argumentos de tipo

Deben ser instancias de tipos de referencia (tipos no primitivos), comodines, parámetros de tipo u otros tipos parametrizados. Por lo tanto, puede definir

List (un tipo de referencia), List (un comodín) o

List

List (parámetro de tipo) en una definición de tipo parametrizada con un parámetro de tipo T .