current position:Home>Deep understanding of generics

Deep understanding of generics

2022-05-15 07:50:34User 7353950

What is the point of introducing generics ?

  • Generics are proposed to write reusability Better code .
  • The essence of generics is parameterized type , That is to say, the data type being operated is Specify as a parameter .

   Before introducing generics , Need to use Object To achieve universal 、 Different types of processing .

Drawbacks as follows :

  • You need to cast to the desired type every time you use it .
  • At compile time, the compiler doesn't know if the type conversion is OK , The runtime knows , unsafe .

In fact, the main goals of introducing generics are the following :

Type safety :

  • The main goal of generics is to improve Java The type of program is safe
  • At compile time, you can check out the cause of Java It's caused by the wrong type ClassCastException abnormal
  • In line with the principle that the earlier the error, the less the cost

Eliminate casts :

  • A side benefit of generics is , Get the target type directly , Eliminate many casts
  • What you get is what you need , This makes the code more readable , And reduces the chance of error and potential performance benefits

Potential performance benefits :

  • Because of the way generics are implemented , Supports generics ( almost ) Unwanted JVM Or class file change
  • All the work is done in the compiler
  • Compiler generated code does not use generics ( And cast ) The code you write is almost the same , It's just more type safe

The use of generics

   The essence of generics is parameterized type , That is, the data type being manipulated is specified as a parameter .

This parameter type can be used in a class 、 Interface and method creation , Known as Generic classes 、 Generic interface 、 Generic methods .

Generic classes : The most common use of generic classes is as container classes that hold different types of data , such as Java Collection container class .

Generic interface : The implementation class needs to specify the specific parameter type when implementing the generic interface , Otherwise, the default type is Object type .

Generic methods : If the class is generic , Directly use the parameters declared by the class , If not , You need to declare the parameter type yourself .

Generic wildcard

<?>: Unlimited wildcards , It means that you can hold any type of .

<?> and <Object> Dissimilarity ,<?> Indicates an unknown type ,<Object> Represents any type of .

<? extends E>:

Use... In type parameters extends Indicates that the parameter in this generic must be E perhaps E Subclasses of , This has two advantages :

  • If the type passed in is not E perhaps E Subclasses of , Editing failed .
  • You can use... In generics E Methods , Otherwise, it has to be transformed into E Can be used .

<? super E>:

Use... In type parameters super Indicates that the parameter in this generic must be E perhaps E Parent class of .

Summary :

  • Unlimited wildcards <?> and Object Somewhat similar , be used for Represents a scene with unlimited or uncertain scope .
  • Two types of restricted general distribution < ? super E> and < ? extends E> It's also easy to confuse , Let's compare .
  • Their purpose is to Make method interfaces more flexible , A wider range of types are acceptable .
  • < ? super E> be used for Write or compare flexibly , Enables objects to write to containers of the parent type , So that the comparison method of parent type can be applied to subclass objects .
  • < ? extends E> be used for Flexible reading , Make the method readable E or E Container object of any subtype of .

Basic principles of using wildcards :

  • If the parameterized type represents a T The producers of , Use < ? extends T>;
  • If it represents a T The consumer , Just use < ? super T>;
  • If it is both production and consumption , Then there's no point in using wildcards , Because what you need is the exact parameter type .
  • T The producer of means that the result will return T, This requires returning a specific type , There must be an upper limit to be specific ;
  • T Consumers mean to operate T, This requires the container to be large enough , So the container needs to be T Parent class of , namely super T;

Generic type erasure

Written in generics Java Program and ordinary Java The procedure is basically the same , It's just More parameterized types and less type conversions .

In fact, generic programs are first transformed into general programs 、 Without generics Java It's handled after the program , The compiler is automatically completed from Generic Java To ordinary Java Translation ,Java The virtual machine runtime knows nothing about generics .

When compiler pairs with generics java When the code is compiled , It will carry out Type checking and type inference , Then generate normal bytecode without generics , This ordinary bytecode can be used by general Java The virtual machine receives and executes , This is called Type Erasure (type erasure).

All in all , A generic is a syntax sugar , It runs without storing any type of information .

The case of generics is called Immutability , The corresponding concept is covariance 、 Inversion :

  • Covariance : If A yes B Parent class of , also A The container of ( such as List<A>) It's also B The container of (List<B>) Parent class of , It is called covariant ( Father son relationship is consistent ).
  • Inversion : If A yes B Parent class of , however A The container of yes B Subclasses of containers , It is called inversion ( Put it in the container and usurp the throne ).
  • immutable : Regardless of A B What does it matter ,A The container and B All containers have no parent-child relationship , Call it immutable .

Java The array in is covariant , Generics are immutable .

   If you want a generic class to be covariant , It needs to be used The border .

  • We know , The generic runtime is erased to the original type , This makes many operations impossible .
  • If the boundary is not specified , The type parameter will be erased as Object.
  • If we want the parameter to keep a boundary , You can set a boundary for the parameter , The generic parameter will be erased to its first boundary ( There can be multiple boundaries ), In this way, even after runtime erasure, there will be scope .

Generic rules

  • The parameter type of a generic type can only be class ( Including custom classes ), Cannot be a simple type .
  • The same generic type can correspond to multiple versions ( Because the parameter type is uncertain ), Different versions of generic class instances are incompatible .
  • generic Type parameters can have multiple .
  • Parameter types of generics have access to extends sentence , Used to be called “ Bounded type ”.
  • Parameter types of generics It can also be a wildcard type , for example Class.

Generic usage scenarios

When the reference data type to be operated in the class is uncertain , Used to use Object To complete the expansion ,JDK 1.5 Post recommendation Use generics to complete extensions , At the same time, ensure safety .

Java in List<Object> And the original type List The difference between ?

The main difference between primitive types and parameterized types is :

  • At compile time, the compiler does not perform type safety checks on the original types , But it will check the security of types with parameters .
  • By using Object As a type , You can tell the compiler that the method can accept any type of object , such as String or Integer.
  • You can pass any type with parameters to the original type List, But it can't put List<String> Pass it on to the receiver List<Object> Methods , Because of the immutability of generics , There will be compilation errors .

copyright notice
author[User 7353950],Please bring the original link to reprint, thank you.

Random recommended