Container-Generic Summary

Container-Generic

  1. Definition of generics:

    **Generic "understand"** is a placeholder for the data type (similar to: formal parameters), telling the compiler that the actual type must be passed in when calling the generic. This parameter type can be used in classes, interfaces, and methods, which are called generic classes, generic interfaces, and generic methods, respectively.

  2. Generic character
    Insert picture description here

  3. Generic class

    • Create a generic class Generic

      /泛型类,定义泛型:<T>是用于普通类
      public class Generic<T> {
              
              
          private T flag;//如果这里没用到泛型,我们要先要定义一个  Object object = new Student();
          // 再用object instanceof Student,判断是否是String、integer这些引用类型
          // 如果是,当我们要调用这个属性的时候,就要把他强转成String类型或者是integer类型,,否则就会报类型转换异常
          //有了泛型之后,这些就变得简单了,也不要去定义Object,也不用去强转,直接在属性面前加一个T的泛型标记
          // 通通帮你搞定,他会再你调用的时候帮你直接转成String这些引用类型。
      
          public void setFlag(T flag){
              
              
              this.flag=flag;
          }
      
          public T getFlag(){
              
              
              return this.flag;
          }
      
      }
      
      
    • Use another test class Test

      //当我们用泛型的时候,才能定义泛型的类型,否则我们是不知道的
      public class Test {
              
              
          public static void main(String[] args) {
              
              
              Generic<String> generic=new Generic<>();
              //如果这里 Generic<String> 没有给定时String类型,generic.setFlag();的时候是Object
              generic.setFlag("admin");
              String flag=generic.getFlag();//如果这里不是泛型来调用的话,要先把他搞成Object,再
              // 用instanceof去判断,是否是String类型,是的话调用要进行强转成String类型,
              //但是这里是泛型的话,直接就可以调用,因为它帮你自动转换成String类型
              System.out.println(flag);
      
      
              Generic<Integer> generic1=new Generic<>();
              generic1.setFlag(100);
              Integer flag1=generic1.getFlag();
              System.out.println(flag1);
      
          }
      }
      
      
  4. Generic interface

    • First establish an Igeneric generic interface.

      //泛型接口,在接口时使用泛型类型
      public interface Igeneric<T> {
              
              
          T getName(T name);//当接口使用泛型类型时,方法的类型也可以使用泛型,方法的参数类型也可以使用泛型。
      
      }
      
    • Define an interface implementation class of IgenericImpl

      //接口实现类,因为Igeneric是泛型的接口,所以要使用具体的泛型Igeneric<String>
      public class IgenericImpl implements Igeneric<String> {
              
              
      
          @Override
          public String getName(String name) {
              
              //为什么方法类型和方法参数都是String类型,
                                              // 因为你上面实现的是具体的接口时是String类型
              return name;
          }
      }
      
    • Another test class Test2

      public class Test2 {
              
              
          public static void main(String[] args) {
              
              
              //对于实例化对象的引用,现在有两种方法,
              //1.接口实现类的类型来定义
              IgenericImpl igeneric=new IgenericImpl();
              String name = igeneric.getName("oldru");//getName();是自动转成String类型的,因为IgenericImpl类的重写方法都是String类型
              System.out.println(name);
      
              //2.接口类型来定义
              Igeneric<String> igeneric1=new IgenericImpl();//这里要特别注意,因为Igeneric是泛型<T>,
              // 还没给具体的String类型,你这里就要加<String>具体的类型,否则你的getName();还是Object类型
              String name1=igeneric1.getName("bjxt");
              System.out.println(name1);
          }
      }
      
  5. Generic methods: Generics are no longer defined on generic classes and used generic methods, but instead are directly loaded with generic definitions on methods. There can be multiple parameter types, separated by commas. Such as: <K,V>.

    **The advantage of this is: **When calling a generic method, you don't need to tell the compiler what type is like a generic class, and the compiler will automatically convert it for you.

  6. Generic static method:

    • First create a generic method of the MethodGeneric class, this is a non-static method

      public class MethodGeneric {
              
              
      
          //之前的是先把泛型定义在类上,然后再通过类上的泛型,去用在方法上的。
          //现在不是,直接把泛型定义装在方法上
          //泛型用在方法上,注意<T>要写在返回值类型的前面  //这是没有返回值的非静态方法
          public <T> void setName(T name){
              
              
              System.out.println(name);
          }
      
          //定义有返回值的非静态方法
          public <T> T getname(T name){
              
              
              return name;
          }
      }
      
      
    • In the definition of a test class Test3

      public class Test3 {
              
              
          public static void main(String[] args) {
              
              
              //测试的是没有返回值的非静态方法
              MethodGeneric methodGeneric=new MethodGeneric();
              //这里的MethodGeneric,不用再去强调具体是什么类型了,因为你在调用的时候,编译器会自动帮你转换
              methodGeneric.setName("oldlu");
              methodGeneric.setName(12312313);
      
      
              //测试的是有返回值的非静态方法
              MethodGeneric methodGeneric2=new MethodGeneric();
              String name=methodGeneric2.getname("bjsxt");//getname();的类型是根据我们这个name属性的String类型推断出来的
              Integer name1=methodGeneric2.getname(123);//getname();的类型是根据我们这个name1属性的Integer类型推断出来的
              System.out.println(name1);                  //所以,才能正常打印
              System.out.println(name);
      
          }
      }
      
      
  7. Generic static method:

    • First create a generic method of the MethodGeneric class, which is a static method.

      public class MethodGeneric {
              
              
           //定义的是没有返回值的静态方法
          public static <T> void setFlag(T flag){
              
              
              System.out.println(flag);
          }
      
          //定义的是有返回值的静态方法
          public static <T> T getFlag(T flag){
              
              
              return flag;
          }
      }
      
      
    • Create another test class Test4

      public class Test4 {
              
              
          public static void main(String[] args) {
              
              
              //调用静态方法是不用实例化对象的引用的,直接调用
              //静态方法没有返回值的调用
              MethodGeneric.setFlag("oldlu");
              MethodGeneric.setFlag(123123);
      
              //静态方法有返回值的调用
              String flag=MethodGeneric.getFlag("bjsxt");
              System.out.println(flag);
              Integer flag1=MethodGeneric.getFlag(123132);
              System.out.println(flag1);
          }
      }
      
  8. The difference between non-static methods and static methods of generic methods :

    Non-static methods can obtain generics in two ways. The first is to use the generic methods provided by the generic class from the generic class, and the second is to directly define the generic method directly in the generic method.

    The static method can only be directly defined on the generic method, and cannot be obtained directly from the generic class.

  9. The parameters in the generic method are variable parameters:

    • First create a MethodGeneric class to write the variable parameters of a generic method.

      public class MethodGeneric {
              
              
          //泛型方法的参数是可变参数
          public <T> void method(T... args){
              
              
              for (T t:args){
              
              
                  System.out.println(t);
              }
          }
      
      }
      
    • Create a Test5

      public class Test5 {
              
              
          public static void main(String[] args) {
              
              
              MethodGeneric methodGeneric= new MethodGeneric();
              String[] arr=new String[]{
              
              "a","b","c"};
              Integer[] arr2=new Integer[]{
              
              1,2,3};
              methodGeneric.method(arr);
              methodGeneric.method(arr2);
      
          }
      }
      
      
  10. Generic wildcard : "?" means wildcard, which is used to replace specific types.

    • First define a generic class, which contains the get and set methods that have been introspected.

      //泛型类,定义泛型:<T>是用于普通类
      public class Generic<T> {
              
              
          private T flag;
          
          public void setFlag(T flag){
              
              
              this.flag=flag;
          }
          
          public T getFlag(){
              
              
              return this.flag;
          }
      
      }
      
      
    • Create a ShowMsg class and define a method that specifically outputs the value of flag in the Generic class.

      //Generic<?>  ?就是泛型的通配符
      public class ShowMsg {
              
              
          //这个方法的作用:就是专门输出Generic类中flag的值
          public void showFlag(Generic<?> generic){
              
              
              //Generic<?> 这里如果不是?通配符,你就要定义一个具体的泛型,比<String>泛型
              //但是你如果是Generic<String>,他调用时就只能限定了它只能是<String>才能调用
              //如果是别的,比如<Integer>类型,它就调用不了了
              //所以为了解决这个问题,我们就使用的通配符?,这样调用的时候就什么泛型都可以调用了
              System.out.println(generic.getFlag());
          }
      }
      
      
    • When creating a test class Test6, all types of tests can be printed, just because there are? Wildcard.

      public class Test6 {
              
              
          public static void main(String[] args) {
              
              
              ShowMsg showMsg= new ShowMsg();
              Generic<Integer> generic=new Generic<>();
              //这里的Generic<Integer>本来是要和ShowMsg类的Generic<Integer> 的泛型一样的才能调用
              //但是,因为下面还有不同的泛型要调用,就会冲突了,所以把ShowMsg类的Generic<?>搞成统配符,这样就谁都可以调用了
              //还有注意一个问题Number是Integer的父类,那你的ShowMsg类的Generic<Number> ,是不是以为Number和Integer泛型都可以调用了,
              //答:不是,因为这里的继承关系是没法在这里使用的
              generic.setFlag(20);
              showMsg.showFlag(generic);
      
      
              Generic<Number> generic1=new Generic<>();
              generic1.setFlag(50);
              showMsg.showFlag(generic1);
      
              Generic<String> generic2=new Generic<>();
              generic2.setFlag("oldlu");
              showMsg.showFlag(generic2);
          }
      }
      
      
  11. The upper limit of the generic wildcard: the type of the wildcard is the T class and the subclass of the T class. The latter is the T interface and the subinterface of the T interface.

    • First define a generic class, which contains the get and set methods that have been introspected.

      //泛型类,定义泛型:<T>是用于普通类
      public class Generic<T> {
              
              
          private T flag;
          
          public void setFlag(T flag){
              
              
              this.flag=flag;
          }
          
          public T getFlag(){
              
              
              return this.flag;
          }
      
      }
      
    • Then create a ShowMsg class, which is a generic wildcard of a generic method and is limited by the upper limit.

      //Generic<?>  ?就是泛型的通配符
      public class ShowMsg {
              
              
          //这个方法的作用:就是专门输出Generic类中flag的值
          public void showFlag(Generic<? extends Number> generic){
              
              
              //泛型通配符的上限限定,说明了泛型的类型继承了Number,也就是缩小了范围
              //他的范围只能是Number类型,或者Number类型的子类Integer
               System.out.println(generic.getFlag());
          }
      }
      
    • Create another test class Test6

      public class Test6 {
              
              
          public static void main(String[] args) {
              
              
              //由于泛型统配符的方法被上限限定了,范围只能在Numeber类型和Numeber的子类Interger类型,只有才这两个类型才能调用,其他类型则无法调用
              ShowMsg showMsg= new ShowMsg();
              Generic<Integer> generic=new Generic<>();
              generic.setFlag(20);
              showMsg.showFlag(generic);
      
      
              Generic<Number> generic1=new Generic<>();
              generic1.setFlag(50);
              showMsg.showFlag(generic1);
      
              /*Generic<String> generic2=new Generic<>();
              generic2.setFlag("oldlu");
              showMsg.showFlag(generic2);//这里的泛型统配符的被上限限定了,导致这里的String类型就不能使用*/
          }
      }
      
      
  12. **Lower limit of generic wildcard: **The type of wildcard is T and the parent of T. The latter is the T interface and the parent of T interface.

    Note: This method applies to generic classes.

    • First define a generic class, which contains the get and set methods that have been introspected.

      //泛型类,定义泛型:<T>是用于普通类
      public class Generic<T> {
              
              
          private T flag;
          
          public void setFlag(T flag){
              
              
              this.flag=flag;
          }
          
          public T getFlag(){
              
              
              return this.flag;
          }
      
      }
      
    • Create a ShowMsg class, the generic wildcard of the generic method is limited by the lower limit.

      //Generic<?>  ?就是泛型的通配符
      public class ShowMsg {
              
              
          //这个方法的作用:就是专门输出Generic类中flag的值
          public void showFlag(Generic<? super Integer> generic){
              
              
              //Generic<? super Integer> generic 泛型统配符的下限限定
              //限定的是当前类型和当前类型的父类才能使用
              //这样Integer类型能使用,Integer类型的父类Number也能使用
              
                System.out.println(generic.getFlag())
          }
      }
      
    • Create another test class Test6

      public class Test6 {
              
              
          public static void main(String[] args) {
              
              
              //由于泛型统配符的方法被上限限定了,范围只能在Numeber类型和Numeber的子类Interger类型,只有才这两个类型才能调用,其他类型则无法调用
              ShowMsg showMsg= new ShowMsg();
              Generic<Integer> generic=new Generic<>();
              generic.setFlag(20);
              showMsg.showFlag(generic);
      
      
              Generic<Number> generic1=new Generic<>();
              generic1.setFlag(50);
              showMsg.showFlag(generic1);
                  }
      }
      
  13. Summary of generics:

    Generics are mainly used in the compilation phase . The bytecode class file generated after compilation contains the type information in the generics. **Type compilation parameters will be replaced with Object after compilation, and the virtual machine does not know about generics at runtime. **Therefore, when using generics, there are several errors as follows:

    • Basic types cannot be used for types :

      Such as: Test t; wrong, we can use the corresponding packaging class, Test t;

    • You cannot create objects with type parameters:

      T elm = new T(); The runtime type parameter T will be replaced with Object, and the object of type T cannot be created, which is easy to cause misunderstanding, so it is supported in java.

Guess you like

Origin blog.csdn.net/Xun_independent/article/details/114635545