java泛型

本文深入讲解Java泛型的概念、使用及声明方式,包括容器中泛型的应用、泛型的声明方法、泛型的受限等内容,并探讨了泛型带来的代码灵活性提升和潜在性能优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、泛型的概述

一般的类和方法,只能使用具体的类型,要么是基类,要么是自定义的类类型。如果要编写出应用多种类型的代码,这样就比较难。
java中的多态就是一种泛化机制。比如,一个方法的参数是基类类型,那么这个方法也可以接收该基类的导出类(子类)作为参数。如果基类是final修饰的,那么就不能 这样扩展。局限于java的单继承机制,所以可以让方法的参数接收一个接口,任何实现该接口的类都可以做方法参数,但是,也只能指定特定的接口。
那么,我们需要编写不基于某种类或接口的代码,该怎么办呢?java提供了一种参数化类型机制——泛型,适用于许多类型,可以表示一个广泛的数据类型参数,只使用于引用类型。
泛型表示:<标识符>,标识符:只要是一个合法的标识符即可,一般情况下,只使用一个大写字母表示泛型

二、容器(List)中使用泛型

public class GenericTest {
    public static void main(String[] args) {
        norList();
        genericList();
    }

    static void norList() {
        List norList = new ArrayList(); // 创建一个没有定义泛型的list
        norList.add(1);// 此处int型自动装箱为了Interger型了
        norList.add("abd");
        norList.add('c');
        System.out.println(norList); // [1, abd, c]
    }

    static void genericList() {
        List<String> genericList = new ArrayList<String>();
        genericList.add("abcf");
        // genericList.add(1); //会编译出错,定义了泛型后的list的add方法只能添加那个类型的值,此处为String
        try {
            Class class1 = Class.forName("java.util.ArrayList");
            Method method = class1.getMethod("add", Object.class);
            method.invoke(genericList, 123); //通过反射可以添加其他类型的值,代码编译后的字节码没有泛型了,叫做泛型的擦除。
            method.invoke(genericList, 'f');
            System.out.println(genericList);
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }
}

当创建的集合没有声明泛型时,可以通过add方法添加任何类型的引用类型对象,add方法的参数类型为Object,在其他类没有明显继承有父类时,它们都自动继承自Object类,添加和取出的都只是Object引用。注意:基本类型都会自动装箱包装成他们的包装类。
但是在创建集合的时候声明了泛型,上例为String类型,那么通过add方法就只能添加字符串,添加其他类型的值将会出现编译错误。
如果要向已经声明了泛型的集合中添加其他类型的对象,可以通过反射来实现。这是泛型的擦除,java中的泛型是使用擦除实现的,意味着当你使用泛型的时候,任何具体的类型都被擦除,你只知道你只是在使用一个对象而已。所以java代码编译后的字节码不存在泛型,可以通过反射在运行期间可以添加不同类型的对象。

三、泛型的声明

1)泛型可以声明在方法中:(泛型方法)

public static <标识符> void fun(){}

2)泛型可以声明在类中:(泛型类)

public class 类名<标识符>{
//类体
//泛型可以在类中充当成员变量
//泛型可以再类中充当方法的返回值
//泛型可以在类中充当方法的参数
}

将泛型定义在类、接口或变量,或方法参数中,new该类时就将类型确定下来

public class Mygenerics<S,In> { //<S,In>两种类型组成的泛型
    S s;
    In i;
    void  method(S s) {
        System.out.println(s);
    }
    public static void main(String[] args) {
        Mygenerics<String,Integer>  m = new Mygenerics<String,Integer>();
        m.s="123";
        m.i=1;
        m.method(m.s);
    }
}
3)泛型可以声明在接口中:(泛型接口)

public interface 接口名<标识符>{
//成员
//泛型可以充当接口中方法的返回值
//泛型可以充当接口中方法的参数
}

4)泛型的受限
1)<? extends T >:表示T类或者T类的子类
2)<? super T>:表示T类或者T类的父类
3)<?>:表示任意类型
class A<T>{
    void m(A<?> a) { //<?>:表示任意类型
    }
    public static void main(String[] args) {
        A<Object>  a = new A<Object>();
        A<String>  b = new A<String>();

        a.m(b); //创建的A的实例a是Object类型,已经确定了的,如果将m()方法中的“ ?”换成T,将编译不通过
        b.m(a);

    }

}

四、总结

泛型是一个重要的JAVA语言加强,它使语言更加灵活.
1.消除强制类型转换 泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。
2.潜在的性能收益 泛型为较大的优化带来可能。在泛型的初始实现中,编译器将强制类型转换(没有泛型的话,程序员会指定这些强制类型转换)插入生成的字节码中。但是更多类型 信息可用于编译器这一事实,为未来版本的JVM 的优化带来可能.

以上有错的地方请大神在评论处指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值