JavaSE-泛型

        在JDK1.5以后,Java引入了泛型的概念,这是一种非常重要的实现技术,它可以帮助我们解决程序的参数转换问题。

        泛型的基本语法

class My_Class<T>{
    private T value;
    //......
} 

        其中的<T>被称作类型参数,可以用来指代任何类型,这个字母是可以随便写的,但是出于开发使用中规范的目的,我们经常使用单个的大写字母来代表类型参数。

        T:代表一般的任何类

        E:代表Element,或者代表Exception异常

        K:代表Key

        V:代表Value的意思,通常与K一起配合使用

        所以,如果一个类以<T>的形式定义,那么这个类就是一个泛型类。

        使用泛型类的时候需要注意:泛型只能接受类,所以,所有的基本数据类型必须使用包装类。

class My_Class<T,E>{//泛型可以接受多个类型参数
    private T value;
    private E value2;
    //......
}
public class Main{
    public static void main(String[] args){
        My_Class<String,Integer> my_class1 = new My_Class<String,Integer>();JDK1.5的语法
        My_Class<Integer,String> my_class2 = new My_Class<>();//JDK1.7之后的新语法
    }
}

        我举一个简单的泛型例子

class My_Class<T,E>{
    private T age;
    private E name;
    public void setAge(T age) {
        this.age = age;
    }
    public void setName(E name) {
        this.name = name;
    }
    public T getAge() {
        return age;
    }
    public E getName() {
        return name;
    }
}
public class Main{
    public static void main(String[] args){
        My_Class<Integer,String> my_class = new My_Class<>();//相当于把T设置成Integer,E为String
        my_class.setAge(20);
        my_class.setName("dxy");
        Integer age = my_class.getAge();
        String name = my_class.getName();
        System.out.println("name:"+name+" "+"age:"+age);
    }
}

        泛型可以避免向下转型,代码中引入了泛型后,如果明确的设置了类型,则为设置类型,否则默认为Object类型。

泛型除了可以用来定义类,也可以定义方法,只不过类型参数要写在返回类型之前。

    public <W> void My_Method(W w){
        System.out.println(w);
    }

        方法中的W被称为参数化类型,它不是运行时真正的参数。

        另外,如果是声明过的类型参数,还是可以作为返回值类型的。

    public <W> W My_Method(W w){
        return w;
    }

    泛型方法和泛型类是可以共存的,但是,我们在设置这两者的类型参数时,需要注意一个问题

class My_Class<T>{
    private T age;
    public <T> T My_Method(T t){
        return t;
    }
    public void setAge(T age) {
        this.age = age;
    }
    public T getAge() {
        return age;
    }
}
public class Main{
    public static void main(String[] args){
        My_Class<Integer> my_class = new My_Class<>();
        System.out.println(my_class.My_Method(24));
    }
}
        在段代码里,类的类型参数和方法的类型参数同名,使用起来很容易出现混淆的情况。所以我们最好在类上在设置一个方法的类型参数,这样就可以避免混淆。
class My_Class<T>{
    private T age;
    public <E> E My_Method(E e){
        return e;
    }
    public void setAge(T age) {
        this.age = age;
    }
    public T getAge() {
        return age;
    }
}
public class Main{
    public static void main(String[] args){
        My_Class<Integer> my_class = new My_Class<>();
        System.out.println(my_class.<String>My_Method("dxy"));//调用方法的时候设置方法的类型参数
    }
}

通配符

        引入泛型之后,会出现新的情况:参数的统一问题

class My_Class<T>{
    private T age;
    public void setAge(T age) {
        this.age = age;
    }
    public T getAge() {
        return age;
    }
}
public class Main{
    public static void main(String[] args){
        My_Class<Integer> my_class = new My_Class<>();
        my_class.setAge(20);
        My_Method(my_class);
    }
    public static void My_Method(My_Class<Integer> my_class){
        System.out.println(my_class.getAge());
    }
}

        如果现在My_Method方法接受的泛型类型不是Integer,那么就会出现错误。所以我们需要一种可以接受任意类型的方法。这就是通配符的作用,先看代码。

    public static void My_Method(My_Class<?> my_class){
        System.out.println(my_class.getAge());
    }

        这里使用了 ? 通配符,它的意思时可以接收任何类型,不过,因为我们不知道会接到什么样的类型,所以不能再My_Method方法里对类中的属性进行修改。

        通配符(? extends 类名称):设置泛型上限

                例如 <? exends Number>:表示当前只能接收Number类以及它的子类。

        通配符(? super 类名称):设置泛型下限

                例如<? super String>:表示只能接收String类以及它的父类object类。 

在这里有一点要说明的是:使用泛型上限的时候,既可以用在类型参数上,也可以用在方法参数上。但是由于不确定接收的类型,还是无法对泛型类中的属性进行修改。使用泛型下限的时候,只能用在方法参数上,但是可以对泛型类中的属性进行修改。        

泛型接口

        泛型除了可以定义在类中与方法中,也可以定义在接口中。

interface My_Interface<T>{//泛型接口
    void Method(T t);
}

        对于泛型接口实现子类有两种方法:

        1:在子类定义时继续使用泛型

interface My_Interface<T>{//泛型接口
    void Method(T t);
}

class My_Class<T> implements My_Interface<T>{//子类实现接口,继续使用泛型。不给出具体类型
    @Override
    public void Method(T t) {
        System.out.println(t);
    }
}

        2:子类在实现接口的时候就给出具体的类型

interface My_Interface<T>{//泛型接口
    void Method(T t);
}

class My_Class implements My_Interface<Integer>{//子类实现接口,给出具体类型
    @Override
    public void Method(Integer t) {
        System.out.println(t);
    }
}

类型擦除

        JDK1.5以后引入了类型擦除的概念,类型擦除的意思大概是这样的

            泛型信息只存在于代码的编译阶段,在进入JVM之前,与泛型相关的信息都会被擦除掉,专业点来说,这就叫做类型型擦除。所以说,普通的类与泛型类在JVM里基本是一样的。

        通过下面的代码来演示一下类型擦除

class My_Class<T extends String,E>{
    private T massaget;
    private E massagee;
}
public class Main {
    public static void main(String[] args) {
        My_Class<String, Integer> my_class = new My_Class<>();
        Class cls = my_class.getClass();
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getType());
        }
    }
}


结果为:


        结论:在类型被擦除的时候,之前泛型类中的类型参数如果没有指定上限,则会被转成Object类型,如果给定了上限,那么就会被替换成类型上限。

        

           我的总结先到这里,后续我会继续补充。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值