Java中的泛型

概念:

java泛型是j2se 1.5引入的新特性,本质是参数化类型,将用到的数据类型指定为任意一种,可用在类、接口、方法中。可以用任意字母来表示,但一般使用大写字母T(Type的简写)来表示。

为什么要有泛型:

在j2se 1.5之前,java允许我们构建一个元素类型为Object的集合,我们可以对类型Object的引用来实现参数的“任意化”,这时编译是没有问题的,
但是在运行期间会出现问题,这是一个安全隐患,为了解决此问题,java 1.5 引入了泛型。

当我们不使用泛型的时候:

public class TestArrayList {
	 public static void main(String[] args) {
		
        ArrayList list1 = new ArrayList();//没有声明泛型的集合  
        list1.add("abc");//添加String类型
        list1.add(123);//添加Integer类型,编译阶段不会报错

        String str1 = (String) list1.get(0);
        String str2 = (String) list1.get(1);//运行期间会报错
	}
}

上面的例子表示在不声明泛型的时候,这个集合里面可以放任意类型的数据,并且在编译期间不显示错误,却出现了安全隐患。一个集合里面放多种类型的数据,没有做到解耦和单一职责,这样也是不推荐的。

当我们使用泛型的时候:

public class TestArrayList {
    public static void main(String[] args) {

        ArrayList <String>list1 = new ArrayList<String>();
        list1.add("abc");
        list1.add(123);//在编译阶段就会提示错误,避免隐患。
	}
}

泛型的使用

一、泛型类的使用

当我们不知道未来属性类型的时候,这种情况可以使用类型占位符进行占位

单个泛型的使用

下面声明一个泛型类

public class Person<T> {
    private T name;
    private T address;

    public T getAddress() {
        return address;
    }

    public void setAddress(T address) {
        this.address = address;
    }

    public T getName() {
        return name;
    }

    public void setName(T name) {
        this.name = name;
    }
}

我们在使用的时候,设定好属性的类型之后,就只能传入指定的泛型类型。

public class TestArrayList {
    public static void main(String[] args) {
        
        Person<String> person = new Person<String>();
        person.setName(123);//编译期间会报错;提示类型不匹配
        person.setAddress("China");
  	}
}

多个泛型的使用

上面的Person类中声明了两个属性,但是如果我想让这两个属性的类型是不一样的怎么办?这个时候可以声明多个泛型。
声明一个泛型类:

public class Animal<K,V> {

    private K name;
    private V age;

    public K getName() {
        return name;
    }

    public void setName(K name) {
        this.name = name;
    }

    public V getAge() {
        return age;
    }

    public void setAge(V age) {
        this.age = age;
    }
}

我们在调用的时候,只能按照泛型类型声明的顺序给属性赋值。
下面String 和Integer的声明顺序分别对应泛型类中name 和age的声明顺序。

public class TestArrayList {
    public static void main(String[] args) {
        
        Animal<String, Integer> animal = new Animal<String, Integer>();
        animal.setName("Tom");
        animal.setAge(18);
    }
}
       

二、泛型方法的声明

普通的泛型方法

泛型类以及方法的声明:

public class Person1<T,K> {
    public void showName(T name) {
        System.out.println(name);
    }

    public void showAge(K age){
        System.out.println(age);
    }
}

方法的调用:

public class TestArrayList {
    public static void main(String[] args) {
        
        Person1<String,Integer> person1 = new Person1<String,Integer>();
        person1.showName("Jack");
        person1.showAge(19);
	}
}

静态的泛型方法

静态泛型方法中的类型占位符和类中的占位符是没有关系的。
这是因为不用static修饰的方法和所在的类不是同一级别,运行时只会加载类,不会加载非static修饰的方法和变量;而用static修饰的方法是和类同一级别的,都是在类加载的时候进行初始化,所以类上面的泛型类型无法应用于static修饰的方法里面。它俩各论各的。

public class Person1<T,K> {
    public void showName(T name) {
        System.out.println(name);
    }

    public void showAge(K age){
        System.out.println(age);
    }
    //静态方法中的泛型和类中的泛型没有关系,所以此行代码会报错
    public static void show2( T t){
        System.out.println(t);
    }

在这里插入图片描述
如果想要在static修饰的方法里面使用泛型,应该使用如下写法:
在static后面先声明泛型,然后在参数中声明泛型变量。

在这里插入图片描述
调用方法:

public class TestArrayList {
    public static void main(String[] args) {
        Person1.show2("Jerry");
    }
 }

另外,如果想让方法只依赖于自己的泛型,直接在方法的public后面声明即可。

public class Person1<T,K> {
	public <S> void show3(S name) {
        System.out.println(name);
    }
}

调用:

public class TestArrayList {
    public static void main(String[] args) {

        Person1<String,Integer> person1 = new Person1<String,Integer>();
        person1.show3(111);
     }
 }

三、泛型接口

首先在接口中声明泛型

public interface IPlant<T> {
    public void eat(T t);
}

实现类A实现该接口

public class Flower implements IPlant<Integer> {
    public void eat(Integer integer) {
  
    }
}

实现类B实现该接口

public class Tree implements IPlant<String >{
    public void eat(String string ) {

    }
}

由此可见,不同类型的实现类可以实现相同的接口,但是如果泛型接口的实现类没有指定具体的泛型类型,必须要在这个实现类中声明一个泛型类型占位符。如下:

public class Flower<T> implements IPlant<T> {
    public void eat(T integer) {
    
    }
}

四、泛型擦除模式

java中的泛型只存在于代码编译阶段,在运行期间泛型类型是会被去除掉的,这个就叫做擦除模式。
如下代码输出的结果显示为true
在这里插入图片描述
如上两个集合的类型不同,但是比较他们的class,返回的却是true,说明在运行阶段,java消除了泛型的类型。
其实在运行阶段它默认的形式如下:

Person p1= new Person();
Person p2= new Person();

泛型擦除的原因有两种说法:
1、为了兼容jdk老版本的编码,之前jdk有一个list,现在也有一个,如果不擦除会有冲突。
2、为了防止创建泛型时造成过度资源消耗。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值