泛型

通用栈

class ObjectStack {
    private Object[] elem;
    private int top;
public ObjectStack(){
     this(10);
}
public ObjectStack(int size){
     this.elem = new Object[size];
      this.top = 10;
   }
public void push(Object val) {
this.elem[this.top++] = val;
   }
}

不适用于大数据的情况。

泛型

  • Java库中包含集合类java.util.ArrayList,可用来存储任何引用或值类型。
泛型引例
import  java.util.ArrayList;
public class ArrayListDemo {
      public static void main(String[]  args)  {
      //创建整型数组列表
      ArrayList list1 = new ArrayList();
      //ArrayList<Integer> list1 = new ArrayList<Integer>();   //泛型
      list1.add(new Integer(101));
      list1.add(new Integer(102));
      //整型数组列表中的值求和
      int sum1 = 0for(Object o : list1) {
      //for(Integer i : list1) {
            sum1 = sum1 +  (Integer)o;
       }
       System.out.println("result:" + result);
       //创建字符串型数组列表
       ArrayList list2 = new Arraylist();
       ArrayList<String> list2 = new Arraylist<String>();
       list2.add("Hello");
       list2.add("Friend");
       //字符串型数组列表中的值拼接
       String sum2 = " ";
       for(Object o : list2) {
       //for(String s : list2) {
            sum2 = sum2 + (String)o;
      }
       System.out.println("sum2:" + sum2);
    }
 }

Arraylist通用化是通过在类型与通用类Object之间进行强制转换来实现的,添加到ArrayList中的任何引用或值类型都将隐式的向上强制转换为Object;如果项是值类型,则添加时需要进行装箱操作,检索时需要进行拆箱操作。
ArrayList通用化的特点:一是强制转换以及装箱操作和拆箱操作都会降低性能;另一个是缺少编译时类型检查,因为所有项都强制转换为Object,所以在编译时无法阻止 客户端代码执行非法操作。

泛型概念
  • 在泛型类型中,必须通过指定尖括号中的类型参数来声明类型。
    类型参数实际上并不是特定类型,而是类型占位符。(T----->ta只是一个类型占位符 表示GenericStack是一个泛型)
//通用栈   数据少可以,多了就不行
class ObjectStack {
  private Object[] elem;  //数组
  private int top;  //指针
  public ObjectStack(){    //不带有参数的构造函数

      this(10);
  }
  public ObjectStack(int size){    //带有参数的构造函数
      this.elem = new Object[size];
      this.top = 10;
  }
  public void push(Object val) {   //入栈

      this.elem[this.top++] = val;  
  }
  public void pop(){    //出栈
      --this.top;
  }
  public Object getTop(){   //得到栈顶元素
      return this.elem[this.top --];
  }
}

public class ObjectStackDemo {
  public static void main(String[] args) {
      ObjectStack objectStack = new ObjectStack();
      objectStack.push(10);  //装包
      objectStack.push(10.9);
      objectStack.push("tulun");
      String str = (String)objectStack.getTop();//强转一次可以,多次就不行

  }

}
泛型的意义:
   a、可以对类型进行自动检查。====》检查并不是替换,编译期间进行检查   
   b、自动对类型进行转换
泛型是怎么编译的?
  • 类型的擦除机制 》向上擦除》擦除到Object类
  • 在编译器的编译期间,把泛型全部擦除为Object类
  • < >尖括号类的东西没有参与类型组成
    GenericStack genericStack2 = new GenericStack();
    == 打印结果:GenericStack@154617c
用jmap命令查看内存泄露
  • javac:编译 javac -p:运行 jmap : 内存泄漏
  • jps ===> 查看java进程号
  • jmap ==> jmap -histo:live 进程号 > e:\log.txt
  • start e
泛型的坑:

1、不能new泛型类型的数组 new T[];
2、不能new泛型类型的对象 T obj = new T[]
3、不能new泛型类型的对象数组
例如: Object[] obj = new GenericStack[10];
obj[0] = “f jakjfaks”;
obj[1] = 10;
4、不能用简单类型作为泛型类型的参数
5、GenericStack genericStack3 = new GenericStack();
一定记得加<泛型类型的参数>否则就是Object
6、在static方法中,不能使用泛型类型的参数。 原因:static 方法不依赖对象,如果不依赖对象,我就不知道这个T是什么类型,编译的时候拿什么去进行类型检查。

class GenericStack<T>{
   private T[] elem;
   private int top;

   public GenericStack(){
       this(10);

   }

   public GenericStack(int size){
       //this.elem = new T[size];   //不能new泛型类型的数组 new T[size]
       this.elem = (T[])new Object[size];  //强转为T[]
       this.top = 0;
   }

   public void push(T val){   //入栈
       this.elem[this.top++] = val;
   }

   public void pop(){      //出栈
       this.elem[top - 1] = null;  //内存的回收
       -- this.top;
   }
   public T getTop(){   //返回T
       return this.elem [this.top --];
   }
}

class Animal{   //定义一个Animal类

}

public class GenericStackDemo {

   /**
    * 内存泄漏
    * java对象的回收  ====》  gc??????????
    * java中的对象回收,要去gc回收器中去回收
    *gc:当前对象没人使用,gc去回收
    * 用jmap命令查看内存泄露
    * jps  ===> 查看java进程号
    * jmap  -histo:live  进程号   >   e:\\log.txt
    *
    * 面试:  javac  javap  -c   jmap
    * @param args
    * @throws InterruptedException
    */
   public static void main(String[] args) throws InterruptedException {
       GenericStack<Animal>genericStack = new GenericStack<Animal>();
       //GenericStack<int >genericStack2 = new GenericStack<int>();  //不可以,不能用简单类型作为泛型类型的参数
       GenericStack  genericStack3 = new GenericStack();  //一定记得加<泛型类型的参数>,否则就变成了Object
       genericStack3.push(10);
       genericStack3.push(10.99);
       genericStack3.push("fsaljl");
     /*  genericStack.push(new Animal());    //内存的泄露
       genericStack.push(new Animal());
       genericStack.push(new Animal());
       genericStack.pop();   //只是Top下移,内存没有被回收
       System.gc();
       Thread.sleep(100000);  //睡眠*/
   }

   /**
    * 泛型的编译:
    *    类型的擦除机制  ===》 向上擦除,擦除到Object类
    *    在编译器的编译期间,把泛型全部擦除为Object类
    *    <  >尖括号类的东西没有参与类型组成
    * @param args
    */
   public static void main2(String[] args) {
       GenericStack<Integer> genericStack = new GenericStack<Integer>();   //<Integer>没有参与类型生成
       GenericStack<String> genericStack2 = new GenericStack<String>();
       //地址的散列码   HaseCoad
       //GenericStack@16d3586   GenericStack<Integer>   //打印 出来是地址
       //GenericStack@154617c  GenericStack<String>
       System.out.println(genericStack);
       System.out.println(genericStack2);

       System.out.println(int.class );
       System.out.println(String.class);
       System.out.println(GenericStack.class);   //GenericStack<String>不是类
   }

   public static void main1(String[] args) {
       GenericStack<Integer> genericStack = new GenericStack<Integer>();  //push Integer类型
       genericStack.push(10);  //尖括号里面是什么,就只能push什么类型
       genericStack.push(12);
       genericStack.push(15);
       int data = genericStack.getTop();   //泛型自动进行强转
       GenericStack<Double>genericStack2 = new GenericStack<Double>();
       genericStack2.push(10.9);
       genericStack2.push(12.3);
       genericStack2.push(15.1);
       //GenericStack<Integer>[] genericStack3 = new GenericStack<Integer>[10];  //不能new 泛型类型的对象数组
       /*GenericStack<Integer>genericStack = new GenericStack<Integer>();  //push Integer类型
       genericStack.push(10.9); //error
       genericStack.push("fjsajfsa");   // error     Integer类型只能new Integer类型 */
   }

}
泛型的上界 “ T extends Comparable”

( 泛型没有下界)

//写一个通用的算法,找到数组中的最大值
class GenericAlg<T extends Comparable<T>> {     //擦除机制是向上擦除的,所以要规定上界
   public T findMaxVal(T[] array) {
       T max = array[0];
       for (int i = 0; i < array.length; i++) {    //遍历数组
          // if(array[i] > max) {     //引用类型比较
           if(array[i].compareTo(max) > 0) {   //引用类型的比较
               max = array[i];
           }
       }
       return max;
   }
}
/*
class GenericAlg2 {
   //泛型方法
   public T findMaxVal(T[] array) {
       return null;
   }

*/


class GenericAlg2 {
   /**
    * 泛型方法
    * @param array
    * @param <T>
    * @return
    */
   //在static方法中,不能使用泛型类型的参数。  原因:static 方法不依赖对象
   //如果不依赖对象,我就不知道这个T是什么类型?编译的时候拿什么去进行类型检查?
   //findMaxVal依赖GenericAlg2被调用
  public static <T extends Comparable<T>> T findMaxVal(T[] array) {
       T max = array[0];
       for (int i = 0; i < array.length; i++) {
           if(array[i].compareTo(max) > 0) {
               max = array[i];
           }
       }
       return max;
   }
}

public class GenericDemo2 {

   public static void main(String[] args) {
       Integer[] array = {1,2,3,4,5,6,7};
       Double[] array2 = {1.3,0.2,9.9};
       //T:会通过实参的类型推演出泛型类型
       //静态不依赖对象
       System.out.println(GenericAlg2.findMaxVal(array));

       System.out.println(GenericAlg2.<Integer>findMaxVal(array));  //可以指明用什么类型进行检查

       System.out.println(GenericAlg2.findMaxVal(array2));
   }
   public static void main1(String[] args) {
       //这样每次都要生成对象,改成static静态的就不依赖对象了
       Integer[] array = {1,2,3,4,5,6,7};
       GenericAlg<Integer> genericAlg = new GenericAlg<Integer>();
       System.out.println(genericAlg.findMaxVal(array));

       Double[] array2 = {1.3,0.2,9.9};
       GenericAlg<Double> genericAlg2 = new GenericAlg<Double>();
       System.out.println(genericAlg2.findMaxVal(array2));
   }
}
通配符 : ? 擦除机制===》擦除到Object

通配符的下界 找到是不是有T的基类实现了Comparable接口 ( ? super T _ 下界主要用来读取
通配符的上界 ( ? extends T ) 上界主要用来写入 一般用作库的开发
&emsp 示例:写一个算法:找到集合当中的最大值

/**
 * Integer继承Number,Number继承Object
 * ArrayList<Integer>    ArrayList<Number>   ArrayList<Object>   这些不可以构成继承关系
 *
 * Integer      ArrayList<Integer>
 * Number       ArrayList<Number>
 * Object       ArrayList<Object>   这些不可以构成继承关系
 */

class GenericAlg3 {  //定义一个类
    public static <T> void printlist1(ArrayList<T> list) {
        //foa   each语句
        for (T obj : list) {  
            System.out.println(obj + " ");
        }
        System.out.println(); //回车
    }
    //?  :  通配符   擦除机制===》 Object
    public static void printlist(ArrayList<?> list) {   
    //不知道实例化的参数是什么类型,通通接受,然后用擦除机制擦到Object       
     for (Object obj : list) {
            System.out.println(obj + " ");
        }
        System.out.println();
    }
}

public class GenericDemo3 {

    public static void main(String[] args) {
        ArrayList<Integer>arrayList = new ArrayList<Integer>();
        arrayList.add(10);
        arrayList.add(14);
        arrayList.add(12);
        arrayList.add(18);
        GenericAlg3.printlist(arrayList);   //void类型不能打印,直接调用

       /* ArrayList<Object> arrayList2 = new ArrayList<Integer>();
        arrayList2.add("10");
        arrayList2.add(10);*/
    }
}
通配符的应用
//找到集合中的最大值
class GenericAlg4 {
    public static <T extends Comparable<T>> T findMaxVal1(ArrayList<T> list) {
        T max = list.get(0);
        for (int i = 0; i < list.size(); i++) {
            if(max.compareTo(list.get(i)) < 0) {
                max = list.get(i);
            }
        }
        return max;
    }
    /**
     * 通配符的下界:找到是不是有T的基类实现了Comparable接口
     * 主要用来读取
     */

    public static <T extends Comparable<? super T>> T findMaxVal2(ArrayList<T> list) {  //T代表student
        T max = list.get(0);
        for (int i = 0; i < list.size(); i++) {
            if(max.compareTo(list.get(i)) < 0) {
                max = list.get(i);
            }
        }
        return max;
    }

    /**
     * ArrayList<? extends T> 上界  主要用来写入
     * @param list
     * @param <T>
     * @return
     */
    public static <T extends Comparable<T>> T findMaxVal(ArrayList<? extends T> list) {
        //擦除到Person就行,就是找通配符的下界
        T max = list.get(0);
        for (int i = 0; i < list.size(); i++) {
            if(max.compareTo(list.get(i)) < 0) {
                max = list.get(i);
            }
        }
        return max;
    }

}
class  Person implements Comparable<Person>{    //Person实现Comparable
    private String name;
    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }

    @Override
    public int compareTo(Person o) {   //根据名字比较大小
        return name.compareTo(o.name);
    }
}
class Student extends Person {
    private int age;
    public Student(String name,int age) {  //实现基类的属性
        super(name);
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                '}';
    }
}

public class GenericDemo4 {
    public static void main(String[] args) {
        ArrayList<Person> arrayList = new ArrayList<Person>();
        arrayList.add(new Person("gaobo"));
        arrayList.add(new Person("tulun"));
        GenericAlg4.findMaxVal(arrayList);
        System.out.println(GenericAlg4.findMaxVal(arrayList));

        ArrayList<Student> arrayList2 = new ArrayList<Student>();
        arrayList2.add(new Student("gaobo", 18));
        arrayList2.add(new Student("tulun", 12));
        System.out.println(GenericAlg4.findMaxVal(arrayList2));
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值