通用栈
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 = 0;
for(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));
}
}