加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java之泛型

发布时间:2020-12-15 06:43:44 所属栏目:Java 来源:网络整理
导读:什么是泛型? 泛型是JDK1.5新加入的,解决数据类型的安全性问题,其主要原理是在类声明时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这样在类声明或实例化时只要指定好需要的具体的类型即可。 为什么要有泛型? java泛型可以保证

什么是泛型?

泛型是JDK1.5新加入的,解决数据类型的安全性问题,其主要原理是在类声明时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这样在类声明或实例化时只要指定好需要的具体的类型即可。

为什么要有泛型?

java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮。

java中的泛型只有在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息檫出,并且在对象和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行阶段。

举个例子:在利用泛型声明一个集合之后,例如List<String> list = new ArrayList<String>();在进行list.add(1);时就会提示:The method add(int,String) in the type List<String> is not applicable for the arguments (int),此时仍处于编译阶段。

怎么使用泛型?

1.泛型类

package collections;

import java.util.ArrayList;
 java.util.List;

public class Test6 {
    static void main(String[] args) {
        A<String> a1 = new A<String>();
        //这里setKey中接受的参数为String类型,因为在实例化的时候声明了String泛型
        a1.setKey("a");
        System.out.println(a1.getKey());
        A<Integer> a2 = new A<Integer>这里setKey中接受的参数为Integer类型,因为在实例化的时候声明了Integer泛型
        a2.setKey(1);
        System.out.println(a2.getKey());
        A a3 = new A();
        假设不指定泛型,那么默认接受为Object
        a3.setKey(1);
        System.out.println(a3.getKey());
        同样的类,指定了不同的泛型,就不能进行相互赋值,比如a1=a2
    }
}
此处的泛型T可以任意取名,一般用T,表示Type
class A<T>{
    private T key;
     setKey(T key){
        this.key = key;
    }
    public T getKey(){
        return this.key;
    }
}

2.泛型接口

 Test7 {
     main(String[] args) {
        Mm<Integer> mm = new Mm<Integer>();
        mm.test(1);
        这种情况下不能指定泛型
        Mn mn =  Mn();
        mn.test("a");
    }
}
interface M<T>{
    T test(T t);
}
未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需要将泛型的声明也一起加入到类中
class Mm<T> implements M<T>{

    @Override
     T test(T t) {
         TODO Auto-generated method stub
        null;
    }
    
}
传入实参时,则需要都修改成实参
class Mn implements M<String> String test(String t) {
        ;
    }
    
}

3.泛型方法

 Test8 {
     main(String[] args) {
        P<Object> p = new P<Object>();
        p.test("aa"泛型方法在调用前没有固定的数据类型
        在调用时,传入的参数是什么类型,就会把泛型改成什么类型
        p.test1(1);
        p.test1(trueclass P<E>在类上定义的泛型,可以在普通方法中使用
     E e;
    
    static <T>   test3(T t) {
        在静态方法中不能使用类定义的泛型,如果要使用泛型,只能使用静态方法自己定义的泛型
        System.out.println(t);
    }
    
    无返回值的泛型
    public <T>  test(T t) {
        
    }
    有返回值的泛型
    public <T> T test1(T s) {
        System.out.println(.e);
        return s;
    }
    带有可变参数方法的泛型
     test2(T... args) {
        for(T arg:args) {
            System.out.println(arg);
        }
    }
}

4.通配符?

 Test9 {
     main(String[] args) {
        Q q =  Q();
        List<String> list1 = new ArrayList<String>();
        q.test(list1);
        List<Integer> list2 = new ArrayList<Integer>();
        q.test(list2);
    }
}
 Q{
    test里面需要传递一个集合List,但是不知道List里面参数的类型
    void test(List<?> list) {
        
    }
}

有限制的通配符:

  • <? extends Person> [无穷小,Person] 只允许泛型为Person及Person子类的引用调用
  • <? super Person> ?[Person,无穷大] 只允许泛型为Person及Person父类的引用调用
  • <? extends Comparable 只允许泛型为Comparable接口的实现类引用调用
 Q();
        List<B1> b1 = new ArrayList<B1>();
        List<C1> c1 = new ArrayList<C1>();
        List<D1> d1 = new ArrayList<D1>q.test1(b1);传入b1会报错
        q.test1(c1);
        q.test1(d1);
        q.test2(d1);传入d1会报错
        List<M1Impl> m1Impl = new ArrayList<M1Impl>();
        q.test3(m1Impl);
        
    }
}
 list) {
        
    }
    参数的元素数据类型为C1及其子类
    void test1(List<? extends C1> list) {}
    参数的元素数据类型为C1及其父类
    void test2(List<? super C1>void test3(List<? extends M1> list) {}
}
 A1{
    
}
class B1 extends A1{}
class C1  B1{} 
class D1  C1{}
interface M1{}
class M1Impl implements M1{}

(编辑:李大同)

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

    推荐文章
      热点阅读