文章目录
    
    
    
    1. 什么是泛型
   
 泛型,即“参数化类型”,将参数的类型泛化。在声明时不指定参数类型,根据传入的实际参数的类型来决定。是jdk1.5的特性
泛型可以随便写,但默认的规则为:
- E—Element,常用在Java的集合中
- K,V—–key,value 代表Map中的键值对
- N—–Number 代表数字
- T—-Type 类型,如String,Integer等等
注意:基本数据类型不能作为泛型
     在集合中不使用泛型时,可以存储任意类型的
    
     对象
    
    ,集合中的元素是对象。
   
    泛型在编译期有效,可以
    
     动态修改参数类型
    
    ,泛型的底层主要是通过list源码来实现的。
   
 public static void main(String[] args) {
        List<String> list=new ArrayList();
        List<Double> list2=new ArrayList();
        //通过反射获取class文件
        Class aClass = list.getClass();
        Class aClass1 = list.getClass();
        System.out.println(aClass.equals(aClass1));
    }
//输出结果为true,由此可得泛型只在编译期有效,相同的代码,不同的泛型编译以后的class文件相同
    
    
    2. 泛型的使用方式
   
泛型的使用方式有三种分别为:泛型类、泛型接口、泛型方法。
    
    
    泛型类
   
主要规范类型的类型,一个类可以有多个泛型。
public class tyuio<S,N,E>{
    private S name;
    private N age;
    public tyuio(S name, N age) {
        this.name = name;
        this.age = age;
    }
    public S getName() {
        return name;
    }
    public void setName(S name) {
        this.name = name;
    }
    public N getAge() {
        return age;
    }
    public void setAge(N age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "tyuio{" +
                "name=" + name +
                ", age=" + age +
                '}';
    }
    public static void main(String[] args) {
        tyuio t=new tyuio<String,Integer,String>("123",4);//在实例化对象时,可指定泛型,也可不指定泛型。
        //若在实例化时要指定泛型的参数,则必须全部指定,不能部分指定
        System.out.println(t);
    }
}
//编译后的代码为
public static void main(String[] paramArrayOfString)
  {
    tyuio localtyuio = new tyuio("123", Integer.valueOf(4));//此处没有了泛型,且对象名与设定的不同,对4进行了装箱操作转为Integer类型的一个对象
    System.out.println(localtyuio);
  }
}
    
    
    泛型接口
   
创建方式与泛型类相同。
public interface qwr<T> {
    public void eat(T name);
}
class tyuio implements qwr{
    public static void main(String[] args) {
    }
    @Override
    public void eat(Object name) {
    }
}
class tyuio implements qwr<String>{
    public static void main(String[] args) {
    }
    @Override
    public void eat(String name) {
    }
}
//编译后的代码都为
class 
{
} 
class tyuio
  implements qwr
{
  public static void main(String[] paramArrayOfString)
  {
  }
  public void eat(Object paramObject)
  {
  }
}
    
    
    在使用泛型类和泛型接口时需注意
   
- 
泛型类和接口主要在继承和实现时使用。 
- 
未传入泛型的实参时,与泛型类定义的相同,在声明类时,需要将泛型的声明也一起加到类中 class a<T>{ public void eat(Object name) { // return null; } } class b<T> extends a<T>{ public static void main(String[] args) { b w=new b(); } }
- 
接口和类在被继承的时候指定具体的类型,子类将不需要泛型,但所有在接口和父类中使用泛型的地方都要替换成传入的实参类型 class a<T>{ public T eat(T name) { return null; } } class b extends a<String>{ //即b可以不使用泛型,在a中使用泛型的地方都变为了String @Override public String eat(String name) { return null; } public static void main(String[] args) { b w=new b(); } }public interface qwr<T> { public T eat(T name); } public class tyuio implements qwr<Integer>{ @Override public Integer eat(Integer name) { return null; } public static void main(String[] args) { tyuio t=new tyuio(); } }
    
    
    泛型方法
   
一个方法由于传入的参数不同,最终输出的结果也不同。
在泛型方法中 :代表声明此方法为泛型方法,类型为T, F :代表方法的返回值类型
表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
class a{   //方法的返回值类型
    public <F> F eat(String name) {
       //泛型方法
       return null ;
    }
}
    
    
    基本用法
   
class a<T> {
    //此类是一个泛型类
    private T name;
    /*此方法不是泛型方法,因为没有<T>,它是一个普通的成员方法,
    因为泛型类已经声明了泛型T,所以此处的T可以使用,该方法的返回值类型为T类型
    */
    public T getName(T d) {
        return name;
    }
   /*d
   下列方法是错误的,因为类的声明中并未声明泛型B,泛型B在作为返回值和形参时无法被编译器识别。
   public B getName(B d) {
        return name;
    }*/
    public void setName(T name) {
        this.name = name;
    }
    /*下列方法为一个泛型方法,主要体现在使用了<T>,<T>表明该方法为一个泛型方法,并且声明了一个泛型T,T可以出现在任意位置,需注意的是此处的T与泛型类中声明的T是不同类型的*/
    public <T> T lok(a<T> name) {
        T d = null;
        return name.getName(d);
    }
    /*此方法正确,E在public 后被声明(方法声明是被声明),所以即使泛型类中未声明也可以在该方法中可以使用,编译器也能正确识别泛型方法中的泛型
    
    */
    public <E> E lok(E name) {
        E d = null;
        return d;
    }
   /*
   此方法错误因为此方法只是声明了泛型E并未声明N
   public <E> E lok(N name) {
       E d = null;
       return d;
   }*/
   /*
   此方法错误,对于编译器来说N并没有在项目中被声明过,因此编译器不知道如何编译N
   所以此方法不是一个正确的泛型方法的声明
   public  void  lok(N name) {
   }
   */
}
    
    
    泛型方法与可变参数
   
  public void d(T...arg){
       for (T t:arg) {
           System.out.println(t);  
       }
  }
    
    
    静态方法与泛型
   
    需注意:静态方法无法访问类上定义的泛型。如果静态方法操作的引用数据不确定的时候,必须要将泛型定义在方法上。即
    
     如果静态方法要是用泛型的话,必须将静态方法定义为泛型方法。
    
   
class o<T>{
    
    public static  void d(T...arg){
        System.out.println(arg);
    }
//此方法会报错,在静态方法中使用泛型时,无论该泛型类型是否在泛型类中声明,必须将静态方法设定为泛型方法。
    public static <T> void d2(T...arg){
        System.out.println(arg);
    }
//此静态方法使用的泛型正确
    public static void main(String[] args) {
        d();
        d2();
    }
}
    
    
    泛型的通配符和上下限
   
    通配符一般是用
    
     ?
    
    代替具体的类型参数。
   
    
    
    说明
   
- 在实例化对象的时候,不确定泛型参数的具体类型时,可以使用通配符进行对象定义
- 
     
 ?
 
 表示不限定通配符,通常与集合配合使用
- 集合中所用类型,不继承父子关系。如:Base是基类,Child为子类,则List和List不具备继承关系,并且而这没有任何关系
- 
     
 <? extends T>
 
 称为上限通配符,表示T类型及其T子类
- 
     
 <? super T>
 
 称为下限通配符,表示T类型及其父类
    
    
    创建对象时的通配符(new 集合时)
   
    有时候在创建集合时,并不知道集合中要存放的数据是什么,所以就会使用到通配符,案例见:–上限通配符
    
     <? extends T>
    
    –和–下限通配符
    
     <? super T>
    
    –
   
    
    
    无限定通配符<?>
   
- 通常与集合配合使用
- 
     集合中的限定类型,表示集合中只能包含一种类型;不限定类型,表示不限定任何类型。
 
 一旦集合转为不限定类型,不可以向集合中添加数据,只能进行查询集合长度、判断集合是否为空等一些与集合中数据的类型无关的一些操作。
 
- 
     通常与
 
 <? extends T>
 
 和
 
 <? super T>
 
 配合使用
class o{
    public static void main(String[] args) {
        List l=new ArrayList();
        l.add("123");
        l.add("as");
        l.add("aca");
        List <?> l1=l;
        
        l1.add("123");//此处会编译报错,因为一旦集合转为不限定类型,不可以向集合中添加数据
        
        System.out.println(l1.size());
        System.out.println(l1.isEmpty());
        List<String> l2=new ArrayList();
        l2.add("2345");
        l2.add("345");
        System.out.println(l2.size());
        System.out.println(l2.isEmpty());
        List<Double> l3=new ArrayList();
        l3.add(2.3);
        System.out.println(l3.size());
        System.out.println(l3.isEmpty());
    }
}
    
    
    上限通配符
    
     <? extends T>
    
   
<? extends T>
    
     <? extends T>
    
    :表示的意思为T类型及其子类
   
- 
     表示规定范围的类型。比如
 
 <? extends T>
 
 :规定的类型是T类型及其子类
- 表示的集合不能添加元素。
class o{
    public static void main(String[] args) {
        List l=new ArrayList();
        l.add("123");
        l.add("as");
        l.add("aca");
        List <? extends String> l1=l;
//        l1.add("234"); 不可以添加元素
        l1.remove(2);
        Iterator iterator=l.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println(l1.size());
        System.out.println(l1.isEmpty());
    }
}
    
    
    下限通配符
    
     <? super T>
    
   
<? super T>
    
     <? super T>
    
    :表示T类型及其父类
   
- 表示规定范围的类型。
- 在集合中可以添加元素,也可以查询
class o{
    public static void main(String[] args) {
        List l=new ArrayList();
        l.add("123");
        l.add("as");
        l.add("aca");
        List <? super String> l1=l;
        l1.add("234");
//        l1.remove(2);
        Iterator iterator=l.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println(l1.size());
        System.out.println(l1.isEmpty());
        for (int i = 0; i < l1.size(); i++) {
            System.out.println(l1.get(i));
        }
    }
}
    
    
    3.总结
   
泛型的提出只要是为了规范代码中的数据类型,防止在某些地方随便使用。有了泛型就不需要做类型转换了。
 
