泛型

泛型

泛型是一种未知的,不确定的数据类型。
举例:
	ArrayList<E>中的E就是一个泛型,是一个未知的数据类型。
泛型虽然是未知的数据类型,但是并不是一直未知,一直不确定,在我们使用一个类的时候,这个泛型表示的数据类型会被确定下来。
举例:
	ArrayList<Student> 此时这个泛型类型E表示的就是Student类型。

泛型也可以省略,如果省略泛型相当于泛型是Object

泛型好处:
	1. 省略了向下转型的代码。
	2. 将运行时期的问题提前到了编译时期。
public static void main(String[] args) {
        //创建集合,省略泛型 泛型也可以省略,如果省略泛型相当于泛型是Object
        ArrayList list = new ArrayList();
        //添加元素
        //list.add(100); 运行时期报错
        list.add("hello");
        list.add("world");
        list.add("java");
        //遍历集合,输出集合中每一个字符串的长度
        for (Object obj : list) {
            //向下转型
            String s = (String) obj;
            // 因为length是字符串里的方法, obj是object类型,所以没法调用, 多态只能调用父类里的方法。
            System.out.println(s.length());
        }

        System.out.println("===================");
        //创建集合,使用泛型
        ArrayList<String> list2 = new ArrayList<>();
        //添加元素
        //list2.add(100); 编译时期报错
        list2.add("hello");
        list2.add("world");
        list2.add("java");
        //遍历集合,输出集合中每一个字符串的长度
        for (String str : list2) {
        // 省略了向下转型的代码。
            System.out.println(str.length());
        }
    }
  • 泛型擦除
/*
    泛型擦除

    Java中的泛型都是伪泛型,泛型只在源代码阶段有效,一旦编译,泛型就会消失。
 */
    public static void main(String[] args) {
        //创建集合
        ArrayList<String> list = new ArrayList<>();
        list.add("hello");
        list.add("world");
        list.add("java");
        //遍历集合(集合.for)
        for (String s : list) {
            System.out.println(s);
        }
    }
  • 泛型类
泛型是一种未知的,一种不确定的数据类型。
如果在定义类的时候,类名后面写上<T>,就表示在类的范围内定义了一个泛型类型T(不确定的数据类型T)
这种未知的类型T等到我们使用这个类的时候就会被确定出来。
这个T可以使用其他字母代替。
例如:
	public class myClass<T> {
        
	}
  • 泛型方法
泛型方法的定义格式:
	修饰符 <泛型> 返回值类型 方法名(参数列表) {
		方法体;
		return 返回值;
	}
在方法上定义的泛型,需要等到调用方法的时候才能确定。
//平板类
public class Pad {
    public void study() {
        System.out.println("平板学习");
    }
}
//手机类
public class Phone {
    public void call() {
        System.out.println("打电话");
    }
}

/*
    泛型就是一种未知的,不确定的数据类型。
    如果在定义类的时候类名后面写上<T>,那么就表示定义了一个泛型类型T。
    这个T可以在整个类中使用。
    T表示一种未知的,不确定的数据类型。 当我们使用这个类(创建对象),那么这个T表示的数据类型才会明确出来。
    尖括号中的T可以使用任何字母代替

    在类上面定义的泛型等到使用这个类创建对象时就指定了,如果想要延后泛型类型指定的时间,让泛型在调用
    方法的时候指定,那么可以使用泛型方法。
    如果在某个方法上定义了泛型,那么该方法就是泛型方法了

    泛型方法的格式:
        修饰符 <泛型> 返回值类型 方法名(参数类型 参数名) {
            方法体;
            return 返回值;
        }

    在方法上定义的泛型,在整个方法中都可以使用,方法上定义的泛型需要等到调用方法时才能确定该泛型的类型。

    小结:
        如果在类上面(中)定义泛型,该类就是一个泛型类。在类中定义泛型需要使用这个类时才会指定该泛型的类型。
        如果在方法上(中)定义泛型,该方法就是一个泛型方法。在方法中定义的泛型需要调用该方法时才会指定该泛型的类型。

 */

public class Factory<T> {//表示在类的范围内【定义】了一个未知的,不确定的数据类型T。

    //定义方法,方法接收什么类型的参数,就得到什么类型的结果
    //第一个<E>:是在定义泛型,表示在方法中定义了一个未知的,不确定的类型E
    //后面两个E:使用了泛型E作为参数类型和返回值类型。
    public <E> E getSame(E e) {
        return e;
    }


    //定义方法,可以修理任何东西
    //【使用】泛型类型T当做方法的参数类型和返回值类型.
    public T method(T t) {
        //修理...
        return t;
    }


    //定义方法,可以修理任何东西
    /*
    public Object method(Object obj) {
        //修理...
        //返回
        return obj;
    }
    */

    //定义方法,用来修理手机
    /*
    public Phone method(Phone p) {
        //假装修理...
        //返回手机
        return p;
    }
    */

    //定义方法,修理pad
    /*
    public Pad method(Pad p) {
        //假装修理...
        //返回pad
        return p;
    }
    */
}

   public static void main(String[] args) {
        //创建Factory对象
        //尖括号中的Phone表示在【明确(指定)】泛型的类型
        Factory<Phone> f = new Factory<>();
        //调用方法,修理手机
        Phone p = f.method(new Phone());
        //打电话
        p.call();
    }
    public static void main(String[] args) {
        //创建Factory对象
        Factory<Phone> f = new Factory<>();
        //调用getSame方法,接受什么类型的参数,就产出什么结果
        Phone phone = f.getSame(new Phone());
        Pad pad = f.getSame(new Pad());
        String str = f.getSame("aaa");
    }
  • 泛型接口

     如果在定义接口的时候在接口名后面写上<T>,那么这个接口就是一个泛型接口了。
     泛型T表示一种未知的不确定的数据类型。
     
     泛型接口的使用:
     	1. 实现类实现接口的时候,可以直接明确接口中的泛型类型。
     	2. 实现类实现接口的时候,可以不指定接口中的泛型,等到使用实现类的时候再指定
    

泛型接口

/*
    如果在定义接口的时候在接口名后面写上<T>,那么该接口就是一个泛型接口了。


    泛型接口的使用:
        1. 实现类在实现接口时可以直接明确泛型的类型。
        2. 实现类在实现接口时不指定泛型,等到使用该实现类的时候再指定泛型。

 */
public interface MyInterface<T> {//表示在接口中定义了一个未知的不确定的数据类型T

    //定义方法使用泛型类型当做方法参数和返回值类型
    T method(T t);
}
/*
    实现类在实现接口时,可以在接口名后面的尖括号中直接指定接口中的泛型
 */
public class MyClassA implements MyInterface<Phone>{

    @Override
    public Phone method(Phone phone) {
        return null;
    }
}
/*
    实现类在实现接口时不指定泛型,等到使用实现类时再指定

    在定义类或接口的时候,只有在当前类或接口名字后面写的尖括号才是在定义泛型。
 */
public class MyClassB<T> implements MyInterface<T>{
    @Override
    public T method(T t) {
        return null;
    }
}
    public static void main(String[] args) {
        //创建MyClassA对象
        MyClassA ma = new MyClassA();
        //调用方法
        Phone p = ma.method(new Phone());

        //创建MyClassB对象
        MyClassB<Pad> mb = new MyClassB<>();
        Pad pad = mb.method(new Pad());
    }
  • 泛型通配符

     ?表示泛型通配符,可以匹配任何类型的泛型。
     注意:泛型通配符一定要放在参数位置被动匹配,不要主动使用(创建对象时使用)
    
/*
    泛型之间是没有继承关系的。
    比如ArrayList<Object>并不是ArrayList<String>的父类。

    如果想要让泛型可以匹配任何类型,那么可以使用泛型通配符。
    ?表示泛型通配符,可以匹配任何类型的泛型


    注意:
        泛型通配符一定要被动匹配(在方法参数位置使用),不要主动使用(比如创建集合对象的时候泛型为?通配符)。
 */
public class Demo01GenericTest {
    public static void main(String[] args) {
        //创建集合用来保存字符串
        ArrayList<String> strList = new ArrayList<>();
        //添加
        strList.add("hello");
        strList.add("world");
        strList.add("java");
        //调用printArrayList方法,遍历
        printArrayList(strList);

        //创建集合保存整数
        ArrayList<Integer> intList = new ArrayList<>();
        //调用printArrayList遍历
        printArrayList(intList);

        //创建集合(不要主动使用泛型通配符)
        //ArrayList<?> list = new ArrayList<>();
        //list.add();
    }


    /*
        定义方法,可以遍历保存任何元素的ArrayList集合。
     */
    public static void printArrayList(ArrayList<?> list) {//?表示泛型通配符,可以匹配任何类型.
        //遍历集合,输出里面的每一个元素
        for (Object obj : list) {
            System.out.println(obj);
        }
    }
}

- 泛型限定

泛型限定:可以限制泛型通配符的范围。
<? extends A>:表示泛型类型要么是A类,要么是A类的子类。上限
<? super A>:表示泛型类型要么是A类,要么是A类的父类。 下限

泛型的使用场景:主要用于代码的重构或代码的设计。
public class Person {
    private String name;
    private int age;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Person() {
    }

    public Person(String name, int age) {

        this.name = name;
        this.age = age;
    }

    public String getName() {

        return name;
    }

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

    public int getAge() {
        return age;
    }

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

public class Student extends Person{

    //提供带参的构造方法,用来在创建对象时直接给属性赋值
    public Student(String name, int age) {
        //将收到的姓名和年龄交给父类的构造方法完成赋值。
        super(name, age);
    }

    public Student() {

    }
}
public class Teacher extends Person{
    public Teacher() {
    }

    public Teacher(String name, int age) {
        super(name, age);
    }
}

/*
    如果要对?泛型通配符的取值范围进行限制,那么可以使用泛型限定。

    <? extends A>:接收的泛型要么是A类,要么是A类的子类。上限
    <? super A>:接收的泛型要么是A类,要么是A类的父类。下限

    泛型可以用于代码优化,代码重构。


 */
public class Demo02GenericTest {
    public static void main(String[] args) {
        //创建集合保存Student对象
        ArrayList<Student> stuList = new ArrayList<>();
        //添加元素
        stuList.add(new Student("jack", 13));
        stuList.add(new Student("rose", 12));
        stuList.add(new Student("tom", 15));
        //调用printArrayList方法遍历
        printArrayList(stuList);

        //创建集合保存Person对象
        ArrayList<Person> personList = new ArrayList<>();
        printArrayList(personList);

        //创建集合保存Object
        ArrayList<Object> objList = new ArrayList<>();
        //printArrayList(objList); //参数集合的泛型要么是Person要么是Person的子类,不能是Person的父类


        //调用method方法,演示下限
        //method(stuList);//要求参数集合的泛型要么是Person,要么是Person的父类。不能是Person的子类
        method(personList);
        method(objList);
    }

    /*
        定义方法,演示泛型下限
     */
    public static void method(ArrayList<? super Person> list) {//要求参数集合的泛型要么是Person,要么是Person的父类。

    }



    /*
        定义方法,遍历保存Person或者Person子类的集合。
     */
    public static void printArrayList(ArrayList<? extends Person> list) {//参数集合的泛型要么是Person要么是Person的子类
        //对参数集合进行遍历
        for (Person p : list) {
            System.out.println(p);
        }
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值