泛型的小千世界(java)


前言

  如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
  而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!


泛型的小千世界(java)

1、泛型

1.1 概述

本质上就是类型参数化。


1.2 好处

1)、对于开发的功能,代码更加灵活
2)、使代码更加简洁
3)、避免强制转换,造成的程序异常


1.3 泛型的特点

【类型擦除】
代码在进入jvm后,泛型会被擦除掉,这时如果该泛型设置了类型上限,那么转换成该类型上限,否则转换成object类型

代码如下(示例)

//未指定上限
public class Test1<T> {
    
    
    T t;
    public T getValue() {
    
    
        return t;
    }
    public void setVale(T t) {
    
    
        this.t = t;
    }
}
//指定上限
public class Test2<T extends String> {
    
    
    T t;
    public T getT() {
    
    
        return t;
    }
    public void setT(T t) {
    
    
        this.t = t;
    }
}

2、泛型的用法

2.1 泛型接口的列子

利用泛型类声明接口来唱歌

代码如下(示例)

package com.yzy.text;
/*
* 泛型接口
* 
* */
interface Computer<E,F>{
    
      //定义两个泛型
      void makechorue(E x,F y);
}
class Chorus<E,F>implements Computer <E,F>{
    
    
      public void makechorue(E x, F y) {
    
    
            x.toString();  //因为不知道什么类型,所以统一变成字符串
            y.toString();
            
      }
      
}
class Musical{
    
    
      public String toString(){
    
    
            System.out.println("| 5 6 3-| 5  17  56|");
            return "";                                  //弹出String型
      }
}
class Singer{
    
    
      public String toString(){
    
    
            System.out.println("好一朵茉莉花");
            return "";
      }
}
public class Text57OOP35 {
    
    
public static void main(String[] args) {
    
    
      Chorus<Singer, Musical> model = new Chorus<Singer,Musical>();
      Singer singer = new Singer();
      Musical musical= new Musical();
      model.makechorue(singer, musical);
}
}

效果:
在这里插入图片描述


2.2 泛型类例子

利用泛型类来实现求取锥类的体积

代码如下(示例)

/**
* 锥类
* */
class Cone<E>{
    
                        
      double height;
      E bottom;                           //低
      public Cone(E bottom) {
    
    
            this.bottom = bottom;
      }
      public double computeVolume(){
    
    
            String  s = bottom.toString();
            double ss =Double.parseDouble(s);
            return 1.0/3.0*ss*height;
      }
}
/**
* 圆锥底面积
* */
class CircleA{
    
    
      double  radius, area;
      public CircleA(double r) {
    
    
            
            radius = r;
      }
      public String toString(){
    
                               
            
            area=radius*radius*Math.PI;    //Math.PI           π的意思
            return  ""+area;           //double型转换成String型
      }
}
/**
* 四角锥 底面积
* */
class Rectangle{
    
    
      double sidA,sidB,area;
      public Rectangle(double sidA, double sidB) {
    
    
            this.sidA = sidA;
            this.sidB = sidB;
      }
      public String toString(){
    
                           
            
            area =sidA*sidB;
            return ""+area;
      }
      
}
public class Text56OOP34 {
    
    
      public static void main(String[] args) {
    
    
            CircleA circle = new CircleA(10);
            Cone<CircleA> coneone = new Cone<CircleA>(circle);
            coneone.height = 30;
            System.out.println("圆锥体积:"+coneone.computeVolume());
            Rectangle rectangle = new Rectangle(10, 20);
            Cone<Rectangle>  conetwo = new Cone<Rectangle>(rectangle);
            conetwo.height = 40;
            System.out.println("四角锥体积:"+conetwo.computeVolume());
      }
}

效果:
在这里插入图片描述


3.其他

3.1 自定义生成泛型对象

代码如下(示例)

public <E> E objectNewInstance(Class<E> clazz) {
    
    
              E a = null;
              try {
    
    
                      a=clazz.newInstance();
              } catch (Exception e1) {
    
    
                     log.error("创建自定义泛型对象错误:{}",e1);
              }
              return a;
       }

使用:

 E e =  (E)  objectNewInstance(DeclaredDlCurveCompanyTimeVo.class);

3.2 泛型对象 转成 class 对象

代码如下(示例)

public void test(List<F> records) {
    
    
              records.forEach(vo->{
    
    
                     try {
    
    
                           //泛型对象 转成 class 对象
                           Class<? extends Object> clazz = vo.getClass();         
                     } catch (Exception e) {
    
    
                           log.error("反射错误:{}",vo);
                     }
              });    
       }

3.3 继承关系的使用

即设置泛型上限,传入的泛型必须是String类型或者是他的子类

代码如下(示例)

public <T extends String> void test(T t) {
    
    }

3.4 依赖关系的使用

F是继承自E。即传入的类型是E类型或者是E类型的子类

代码如下(示例)

public <E, F extends E> void test(E e, F c) {
    
    }

3.5 通配符

注意: 通配符不能用作返回值
如果返回值依赖类型参数,不能使用通配符作为返回值。可以使用类型参数返回:

public <T> T test (T t){
    
    
  return t;
}

(1) <?> 无限通配符
注意: 无限通配符只能读的能力,没有写的能力。

代码如下(示例)

public void test(List<?> list) {
    
    
     //只允许读数据
      Object o = list.get(0);
     //不允许写数据
     // list.add("1111");
}

(2) <? extends T> 定义上限 表示参数化类型可能是T 或是 T的派生类(子类);
频繁往外读取内容的,适合用上界Extends。

(3) <? super T> 定义下限 表示参数化类型可能是T 或是 T的基类(父类);
经常往里插入的,适合用下界Super

代码如下(示例)

class A{
    
        
}
class B extends A{
    
    
}
class C extends B{
    
    
}
public class Test {
    
    
      public static List<B> b = new ArrayList<>();
      public static List<C> c = new ArrayList<>();
      public static List<A> a = new ArrayList<>();
      
      public static void main(String[] args) {
    
    
            List<? extends B> listextends = null;
            List<? super B> listsuper = null;
            //? extends B   表示参数化类型可能是T 或是 T的派生类(子类);
            listextends = Test.a;  //报错
            listextends = Test.b;
            listextends = Test.c;
            //<? super T> 表示参数化类型可能是T 或是 T的基类(父类);
            listsuper  = Test.a;
            listsuper  = Test.b;
            listsuper  = Test.c;  //报错
      }
}

效果:
在这里插入图片描述

(4) <? super T>和<? extends T> 经典用法

public <T> void copy(List<? super T> dest, List<? extends T> src) {
    
    
            for (int i = 0; i < src.size(); i++)
                dest.set(i, src.get(i));
            }
       }

猜你喜欢

转载自blog.csdn.net/weixin_38316697/article/details/108620152