java泛型学习笔记

本文章是个人学习笔记,如有错误欢迎指正

Java泛型

一、定义和存在意义

定义:允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明,实质是:参数化类型

好处:

  • 类型安全
  • 消除强制类型转换

二、泛型类、接口

泛型类定义:

/**
 * 泛型类定义
 * @param  泛型标识---类型形参,T在创建对象的时候指定具体的数据类型,
 *           由外部使用类来指定
 */
public class Generic {
    private T key;

    public Generic(T key) {
        this.key = key;
    }

    public T getKey() {
        return key;
    }

    public void setKey(T key) {
        this.key = key;
    }
}

泛型类使用:

 Generic stringGeneric=new Generic<>("泛型实参");

注意:

  • 若泛型类在创建对象时候没有指定类型,将视为object类型
  • 泛型类不支持基本数据类型,如int,必须使用Integer来指定
  • 同一泛型类根据不同数据类型创建的对象本质上是同一类型,getClass()相等,所以没法进行方法重载

从泛型类派生子类:

  • 父类是泛型类,子类也是,则要求子类和父类的泛型类型要一致,若继承时父类不指定,则默认Object类

    //父类
    public class Parent {
        private  E key;
    
        public E getKey() {
            return key;
        }
    
        public void setKey(E key) {
            this.key = key;
        }
    }
    //第一种继承方式:
    class Child extends Parent{
        @Override
        public Object getKey() {
            return super.getKey();
        }
    }
    //第二种继承方式:
    class  Child2 extends Parent{
        @Override
        public T getKey() {
            return super.getKey();
        }
    }
    
  • 父类是泛型,子类不是,则要求父类必须明确泛型的数据类型,或者不指定默认Object

    public class Parent {
        private  E key;
    
        public E getKey() {
            return key;
        }
    
        public void setKey(E key) {
            this.key = key;
        }
    }
    class Child3 extends Parent{
        @Override
        public Object getKey() {
            return super.getKey();
        }
    }
    class Child4 extends Parent{
        @Override
        public String getKey() {
            return super.getKey();
        }
    }
    //编译出错
    class Child5 extends Parent{
        @Override
        public Object getKey() {
            return super.getKey();
        }
    }
    

泛型接口定义:

public interface GenericInterface {
    T getKey();
}

泛型接口的使用:

  • 实现接口的类是泛型类,则要求泛型类型一致

    public interface GenericInterface {
        T getKey();
    }
    class Appleimplements GenericInterface{
    
        @Override
        public T getKey() {
            return null;
        }
    }
    
  • 实现接口的类不是泛型类,则要求明确泛型的数据类型

    public interface GenericInterface {
        T getKey();
    }
    
    class Organe implements GenericInterface{
        @Override
        public Integer getKey() {
            return null;
        }
    }
    

泛型方法:

//例如: 
public  E get(ArrayList list){
        return list.get(5);
    }

注:泛型方法也支持静态方法

二|类型通配符

类型通配符使用?代替类型实参,而不是形参

比如

定义泛型类:

class  Box{
    ......
}

定义泛型方法:

注意:泛型类是无法进行泛型重载的

//编译错误
public void showBox(Box box){
......
}
public void showBox(Box box){
......
}

正确定义:

public void showBox(Box box){
......
}

使用

Box b1=new Box();
Box b2=new Box();
showBox(b1);
showBox(b1);

类型通配符的上下限:

上限

//表明该泛型的类型只能是该实参类型,或者是该实参的子类类型
类/接口

下限

//表明该泛型的类型只能是该实参类型,或者是该实参的父类类型
类/接口

三、类型擦除

泛型是jdk1.5引入的,但是泛型可以兼容之前的代码是由于:泛型只存在代码编译阶段,在进入jvm之前就已经将泛型相关信息擦除了。

  • 无限制类型擦除:对于无限制的泛型类型都将默认视为Object类型

  • 有限制类型擦除:对于有上限的泛型类型,将擦除为上限的类型

  • 桥接方法:对于泛型接口中的泛型类型都会默认视为Object类型,在其实现类中,会生成一个有指定类型的实现方法和一个Object类型的实现方法来保持类与接口的实现关系

    擦除之前:

    interface   Box{
        T get(T key);
    }
    class BoxImpl implements  Box{
    
        @Override
        public Integer get(Integer key) {
            return key;
        }
    }
    

    擦除之后:

    interface   Box{
        Object get();
    }
    class BoxImpl implements  Box{
    
    
        public Integer get(Integer key) {
            return key;
        }
        @override
         public Object get(Object key) {
            return get((Integer) key);
        }
    }
    

你可能感兴趣的:(java泛型学习笔记)