加入收藏 | 设为首页 | 会员中心 | 我要投稿 开发网_开封站长网 (http://www.0378zz.com/)- 科技、AI行业应用、媒体智能、低代码、办公协同!
当前位置: 首页 > 教程 > 正文

Java泛型分析

发布时间:2021-12-05 17:48:42 所属栏目:教程 来源:互联网
导读:泛型是Java 5引入的机制, 允许编写不关心具体类型的类或方法. 泛型最著名的应用是Collection框架. ListString list = new ArrayList(); 泛型类List在定义时并不关心元素类型, 只有在实例化时才获得具体的元素类型. 泛型类 声明泛型需要使用声明类型参数, 如T

泛型是Java 5引入的机制, 允许编写不关心具体类型的类或方法. 泛型最著名的应用是Collection框架.
 
List<String> list = new ArrayList<>();
泛型类List在定义时并不关心元素类型, 只有在实例化时才获得具体的元素类型.
 
泛型类
声明泛型需要使用<>声明类型参数, 如<T>, <T1, T2>. 下面的示例中声明了一个Holder类, 它的item域可以存储任意类型的引用.
 
class Holder<T> {
 
    T item;
 
    publicvoidset(T t) {
        item = t;
    }
 
    public T get() {
        return item;
    }
 
    publicstaticvoidmain(String[] args) {
        Holder<String> holder = new Holder<>();
        holder.set("Hello World");
        System.out.println(holder.get());
    }
}
在Java 7之前必须在创建实例时指定类型参数:
 
Holder<String> holder = new Holder<String>();
Java 7提供了类型推断功能, 可以根据声明推断实例的类型参数:
 
Holder<String> holder = new Holder<>();  // 不必在new对象时再写一次类型参数了
或者在return时推断类型:
 
publicstatic Holder<String> getInstance() {
    return new Holder<>();
}
示例中的Holder类没有对类型参数T做任何限制, T可以实例化为任意类型. Java允许我们限制对其进行限制.
 
<T extends MyClass>: T必须为MyClass或其子类
 
<T super MyClass>: T必须为MyClass或其父类
 
比较常用的是extends限定, 因为子类必然定义了父类的方法(和域), 因此我们可以安全地访问父类声明的方法(和域).
 
下面的示例中访问item.length()是安全的, 因为T的基类String定义了该方法.
 
class Holder<T extends String> {
 
    T item;
 
    publicvoidset(T t) {
        item = t;
    }
 
    public T get() {
        return item;
    }
 
    publicintlength() {
        return item.length();
    }
 
    publicstaticvoidmain(String[] args) {
        Holder<String> holder = new Holder<>();
        holder.set("Hello World");
        System.out.println(holder.length());
    }
 
}
泛型方法
Java也允许只为方法而非整个类声明类型参数:
 
public class Main {
 
    public static <T> voidlog(T t) {
        System.out.println(t);
    }
    
    publicstaticvoidmain(String[] args) {
        log(1);
    }
}
类型通配符
在上文示例中, 我们总是在实例化泛型类时指定具体的类代替类型参数, 比如Holder<String>使用String代替类型参数T.
 
类型通配符允许在实例化泛型类时不指定具体类:
 
Holder<?> holder = new Holder<>();
上述示例初始化了一个没有类型限制的Holder实例. 无任何限制的类型通配符可以被省略:
 
Holder holder = new Holder();
除非因为绝对必要的原因, 否则不建议使用无限制的类型通配符. 类型通配符同样可以使用extends和super进行范围限定.
 
Holder<? extends String> holder = new Holder<>();
上述示例中, holder的set方法不能正常编译. 类型通配符通常用于声明方法的参数类型:
 
 
class Holder<T> {
 
    T item;
 
    publicvoidset(T t) {
        item = t;
    }
 
    public T get() {
        return item;
    }
 
    publicstaticvoidprint(Holder<? extends String> holder) {
        System.out.println(holder.get());
    }
 
    publicstaticvoidmain(String[] args) {
        Holder<String> holder = new Holder<>();
        holder.set("Hello World");
        print(holder);
    }
 
}
类型擦除
java的泛型采用运行时类型擦除的方式实现泛型, 也就是说类型参数仅存在于编译期, 运行时虚拟机并不知道泛型参数的存在.
 
publicstaticvoidmain(String[] args) {
    List<String> strings = new ArrayList<>();
    List<Long> longs = new ArrayList<>();
    System.out.println(strings.getClass() == longs.getClass());
}
上文示例输出true, 说明了运行期无法访问类型参数. 泛型是通过编译时添加了类型检查和自动转型的字节码来实现的.
 
数组也受到了类型擦除影响:
 
public class Main {
 
    public static <T> voidprint(T[] arr) {
        for (T t : arr) {
            System.out.println(t);
        }
    }
 
    publicstaticvoidmain(String[] args) {
        String[] strings = {"a", "b", "c", "d"};
        print(strings);
    }
}
上面的代码是可以正常运行的, 但是Java禁止直接创建泛型数组:
 
    public static <T> voidtest() {
        T[] arr = new T[5];
    }
禁止创建泛型数组的原因可以在Java Language Specification中窥见端倪:
 
在10.6 数组初始化中提到
 
[It is a compile-time error if the component type of the array being initialized is not reifiable(4.7)
 
看一下reifiable(物化)的定义:
 
A type is reifiable if and only if one of the following holds:
It refers to a non-generic class or interface type declaration.
It is a parameterized type in which all type arguments are unbounded wildcards (§4.5.1).
It is a raw type (§4.8).
It is a primitive type (§4.2).
It is an array type (§10.1) whose element type is reifiable.
 
因为类型擦除的原因, java.util.ArrayList采用了Object[]来存储元素.

(编辑:开发网_开封站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读