Java中的泛型

快扶我去看书.jpg

由浅入深,没时间解释了,快上车,fuck car!!!

Java中的泛型,相信很多人在开发中都用到,像下面的

public  class  Test  {
    private T  t;
    private   T getData() {
    };
    private interface ITest  {
        T getData();
        T getDatas(T a);
    }
}

是不是很熟悉,很好,觉得熟悉就对了,那下面这个呢,涉及到了泛型的限制,通配符之类的,是不是很眼熟呢~。

//通配符(还有super)
public void  method4(Person<? extends Fruit> p) {
}

public  class  Test  {}

//正确
public  class  Test  {}
//下个却是错的,如果有多个,类要放在第一(ArrayList),接口放在后面(Serializable),语法限制。。。
public  class  Test  {}

上面的错误的原因,请看下图:


image.png

......

唠嗑了下曾经碰到过的,那么,开始吧,提出问题。

1. 什么是泛型
2. 为什么要用泛型
3. 泛型的使用
4. 限定类型变量
5. 泛型使用中的局限性
6. 泛型中的通配符类型
7. 虚拟机是如何实现泛型的

问题提出来了,喝瓶阔落压压惊。


image.png
  1. 什么是泛型

可以这么理解:参数化类型或者类型参数化。什么意思呢?用过方法吧,方法里面传的参数,举个例子:

//方法1
public  int getData(int a) {
}
//方法2
public   T  getData(T a) {
}

方法1把类型参数化,变成方法2,就不再局限于该方法的参数类型只能是int,你可以是String,double等之类的。

  1. 为什么要用泛型
1.多种数据类型使用相同的代码。
2.使用泛型,在编码过程中指定数据类型,不需要强制转换。

3.泛型的使用
泛型主要用在类,接口,方法。

泛型类

public class  Fruit{
}
public class Apple extends Fruit {
}

public class Person  {
}
//派生类
public  class  Demo    extends Person  {
  private List list;
}

 泛型类是可以继承或者扩展其他泛型类的,正确的写法是:
 Person p1 = new Demo(); //里面的类型Apple不能换  成Fruit 
注意: 
  Person p1 = new Person<>();
  Person p2 = new Person<>();
  p1跟p2没有继承关系,如何证明呢,看下面:
  Person p1 = new Person();
  上面代码会报错了~
 

泛型接口

public interface CallBack  {
  void callBack(T a);
}
//接口实现
public class ImpCallBack   implements CallBack  {
...
}
或者具体某个
public class ImpCallBack  implements CallBack  {
...
}

泛型方法

//泛型方法
public  T  methodTest(T t) {
...
}

//注意:下面的method1并不是泛型方法,他只是引用了Demo中的泛型
public  class  Demo    extends Person  {
  public void method1(Demo  demo) {
    ...
  }
}

4.限定类型变量

泛型的限定类型变量,就是限定可以传递的类型。
举个例子(这里就拿  泛型方法做例子, because,泛型类,泛型接口与泛型方法类似。)
public class Person{
}
public class Boy extends Person{
}

public class Aa{
}

此时,我这里有个方法
public  void method2( T t) {
  ...
}
如果需要调用这个方法,只能传递Person或者Person的子类:
  method2(new Boy());
  method2(new Person());
  method2(new Aa());    //错误,这个不行
如果传递的是别的对象,sorry,不行

5.泛型使用中的局限性

不能实例化类型变量
public class Person {
  private T t = new T();
}
上面这情况是不阔以的,语法不允许(报错:type parameter "T" cannot be instantiated directly)
静态域或者静态方法是不能引用类型变量
public class Person {
  private static void method3(T t){
  ...
  }
 private static  void method4(T t){
  ...
  }

}
 //注意
 上面的method3写法是不可以,原因:静态方法的执行比对象的创建 
 要早, 然而new Person()的时候,才知道T的类型。

 当然了,静态方法本身是泛型方法就可以。看method4()方法。
泛型里面不能是基本数据类型
public class Person {
}
使用: new Person() ,是错误的,int需要装箱后放进去。
也就是说,只能是对象,不能是基本数据类型
泛型是不能用instanceof关键字的
举个例子
public class Person {
}
public static void main(String[] args) {
    Person  person;
    if(person instanceof  Person ) {
    }
//是不允许的,不支持
}
泛型类不能继承Exception
//下面这样写,直接就给你飘红了
public class Person extends Exception {
}

看图


image.png
泛型其他有趣的限制
Person[]  person;  //定义可以,没问题,but
person = new Person[5];  //初始化,对不起,不行~

不要问为什么。。。语法限制

6.泛型中的通配符类型
我们来看个例子

//普通类
public class Food {
}
public class  Fruit extends Food{ 
}
public class Apple extends Fruit {
}
//泛型类
public class Person  {
}
....
public void  method3(Person p) {
}
//使用了通配符的
public void  method4(Person<? extends Fruit> p) {
}
public void  method5(Person<? super  Fruit> p) {
}
public static void main(String[] arg) {
   Person p0 = new Person<>();
   Person p1 = new Person<>();
   Person p2 = new Person<>();
  //方法调用
  method3(p1); //这个毫无疑问,是可以的
  method3(p2); // 不可以!!! 
  //这个时候就要使用通配符了
  method4(p1); .// you can
  method4(p2); // 哎,这个也可以了
  method4(p0); //这个不行,看下面说明
  //说明:通配符 extends 限制了上界,比如上面的,上届就是Fruit,
  //只要是派生自Friut或者本身,都可以,Food就不行了(也就是说,只要是 Friut的子类都可以)

  //还没完事呢,通配符除了extends ,还有 super,
  //用法刚好跟extends相反,看method5,只要是 Fruit的超(父)类或者其本身,都可以。
}

7.虚拟机是如何实现泛型的
实不相瞒,进行了泛型擦除。什么意思呢,我举个例子

public class Person {
  private T t;
}
上面的类泛型擦除后,会是下面这个:
public class Person {
  private Object t;
}
继续看
public class Person {
  private T t;
  public void test(){
     // t.compareTo()
  }
}
擦除后这样的:
public class Person {
  private ArrayList t;
  public void test(){
     // (Comparable)t.compareTo()
  }
}
开头就提出来了,如果有继承的,必须放在第一(ArrayList放在Comparable前面),
类只能有一个(因为在java里面,是单继承的),接口可以多个。对于后面的Comparable,什么时候体现呢?
当你在某个方法用到了Comparable接口的时候,编译器会插入一个强制转型的代码,看test()方法。
感兴趣的可以看编译后的.class文件。

over,记录下。

你可能感兴趣的:(Java中的泛型)