泛型的介绍

本次博客带领大家了解泛型的介绍。

泛型说明

  1. 泛型又称参数化类型,是jdk5.0出现的新特性,解决数据类型的安全性问题。
  2. 在类声明或实例化时只要指定好需要的具体的类型即可。
  3. Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常,同时,代码更加简洁、健壮。
  4. 泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型。
public class Generic03 {
    public static void main(String[] args) {
        Person<String> stringPerson = new Person<String>("加油!");
        stringPerson.t();
        /*
            你可以这样理解,上面的Person类
            class Person{
                String s;//E表示 s的数据类型,该数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型

                public Person(String s) { //E也可以是参数类型
                    this.s = s;
                }

                public String f(){ //返回类型使用E
                    return s;
                }
            }
         */
    }
}

class Person<E>{
    E s;//E表示 s的数据类型,该数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型

    public Person(E s) { //E也可以是参数类型
        this.s = s;
    }

    public E f(){ //返回类型使用E
        return s;
    }

    public void t(){
        System.out.println(s.getClass());
    }
}

泛型的语法

  • 泛型的声明

interface 接口{} 和 class 类<K,V>{}

//比如:List,ArrayList

说明:

  1. 其中,T,K,V不代表值,而是表示类型。
  2. 任意字母都可以。常用T表示,是Type的缩写。
  • 泛型的实例化:

要在类名后面指定类型参数的值(类型)。如:

  1. List strList = new ArrayList();
  2. Iterator iterator = customers.iterator();
  • 泛型的使用举例
    1. 创建3个学生对象
    2. 放入到HashSet中学生对象使用
    3. 放入到HashMap中,要求Key是String name,Value 就是学生对象
    4. 使用两种方式遍历
public class GenericExercise {
    public static void main(String[] args) {
        //使用泛型方式给HashSet 放入3个学生对象
        HashSet<Student> set = new HashSet<Student>();
        set.add(new Student("jack",20));
        set.add(new Student("tom",19));
        set.add(new Student("smith",21));

        //遍历
        System.out.println("========增强for遍历======");
        for (Student student : set) {
            System.out.println("set="+student);
        }
        System.out.println("========迭代器遍历=======");
        Iterator<Student> iterator = set.iterator();
        while (iterator.hasNext()) {
            Student student =  iterator.next();
            System.out.println("set="+student);
        }

        HashMap<String, Student> hm = new HashMap<>();
        hm.put("milan",new Student("milan",20) );
        hm.put("marry",new Student("marry",19) );
        hm.put("ld",new Student("ld",21) );


        //迭代器
        System.out.println("=====HashMap的迭代器遍历");
        Set<Map.Entry<String, Student>> entries = hm.entrySet();
        Iterator<Map.Entry<String, Student>> iterator1 = entries.iterator();
        while (iterator1.hasNext()) {
            Map.Entry<String, Student> student = iterator1.next();
            System.out.println(student.getKey()+"--"+student.getValue());
        }

    }
}

class Student{
    public String name;
    public int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

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

泛型使用的注意事项和细节

  1. interface List{},public class HashSet{}…等等

说明:T,E只能是引用类型

给泛型指向数据类型时,要求是引用类型,不能是基本数据类型。

List<Integer> list = new ArrayList<Integer>();//ok
ArrayList<int> ints = new ArrayList<int>();//错误
  1. 在给泛型指定具体类型后,可以传入该类型或者其子类类型。
Pig<A> aPig = new Pig<A>(new A());
Pig<A> aPig2 = new Pig<A>(new B());

class A{}
class B extends A{}

class Pig<E> {
    E e;

    public Pig(E e) {
        this.e = e;
    }
}
  1. 泛型的使用形式:
ArrayList<Integer> integers = new ArrayList<Integer>();
//在实际开发中,我们往往简写
//编译器会进行类型判断,老师推荐使用下面写法
ArrayList<Integer> integers1 = new ArrayList<>();
  1. 如果是这样写 泛型默认是 Object
ArrayList arrayList = new ArrayList();//等价于ArrayList<Object> arrayList = new ArrayList<>();

泛型练习题

定义Employee类

  1. 该类包含:private成员变量name,sal,birthday,其中 birthday 为 MyDate 类的对象;
  2. 为每一个属性定义 getter,setter方法;
  3. 重写toString 方法输出 name,sal,birthday;
  4. MyDate类包含:private成员变量month,day,year;并为每一个属性定义getter,setter方法;
  5. 创建该类的三个对象,并把这些对象放入ArrayList集合中(ArrayList需使用泛型来定义),对集合中的元素进行排序,并遍历输出。

排序方式:调用ArrayList的sort方法,传入Comparator对象[使用泛型],先按照name排序,如果name相同,则按生日日期的先后排序。

public class GenericExercise02 {
    public static void main(String[] args) {
        ArrayList<Employee> employees = new ArrayList<>();
        employees.add(new Employee("tom",20000,new MyDate(1990,1,9)));
        employees.add(new Employee("jack",12000,new MyDate(2001,12,12)));
        employees.add(new Employee("tom",50000,new MyDate(1980,10,10)));

        System.out.println("employees="+employees);
        System.out.println("====对雇员进行排序====");
        employees.sort(new Comparator<Employee>() {
            @Override
            public int compare(Employee emp1, Employee emp2) {
                //先对传入的参数进行验证
                if(!(emp1 instanceof  Employee && emp2 instanceof Employee)){
                    System.out.println("类型不正确...");
                    return 0;
                }
                //比较name
                int i = emp1.getName().compareTo(emp2.getName());
                if(i != 0){
                    return i;
                }
                //下面是对birthday 的比较,因此,我们最好把这个比较,放在MyDate类完成
                //封装后,将来可维护性和复用性,就大大增强。
                return emp1.getBirthday().compareTo(emp2.getBirthday());
                
            }
        });

        System.out.println("employees="+employees);
    }
}

class Employee{
    private String name;
    private double sal;
    private MyDate birthday;

    public Employee(String name, double sal, MyDate birthday) {
        this.name = name;
        this.sal = sal;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

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

    public double getSal() {
        return sal;
    }

    public void setSal(double sal) {
        this.sal = sal;
    }

    public MyDate getBirthday() {
        return birthday;
    }

    public void setBirthday(MyDate birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "\nEmployee{" +
                "name='" + name + '\'' +
                ", sal=" + sal +
                ", birthday=" + birthday +
                '}';
    }
}

class MyDate implements Comparable<MyDate>{
    private int year;
    private int month;
    private int day;

    public MyDate(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public int getDay() {
        return day;
    }

    public void setDay(int day) {
        this.day = day;
    }

    @Override
    public String toString() {
        return "MyDate{" +
                "year=" + year +
                ", month=" + month +
                ", day=" + day +
                '}';
    }


    @Override
    public int compareTo(MyDate o) {
        //如果name 相同,就比较 birthday- year
        int yearMinus = year - o.getYear();
        if (yearMinus !=0){
            return yearMinus;
        }
        //如果year 相同,就比较month
        int monthMinus = month - o.getMonth();
        if (monthMinus != 0){
            return monthMinus;
        }
        //如果 year和 month
        return day - o.getDay();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值