首页IT科技day28–Java泛型01

day28–Java泛型01

时间2025-04-30 13:37:41分类IT科技浏览4070
导读:Java泛型01 1.泛型的理解和好处...

Java泛型01

1.泛型的理解和好处

看一个需求:

请编写程序          ,在ArrayList中添加三个Dog对象 Dog对象含有name和age                 ,并输出name和age(要求使用getXXX())

先用传统的方法来解决--->引出泛型

传统的方法:

package li.generic; import java.util.ArrayList; @SuppressWarnings("all") public class Introduce_ { public static void main(String[] args) { //用传统的方法来解决 ArrayList arrayList = new ArrayList(); arrayList.add(new Dog("旺财",10)); arrayList.add(new Dog("发财",1)); arrayList.add(new Dog("小黄",5)); for (Object o:arrayList) { //向下转型 Dog dog = (Dog) o; System.out.println(dog.getName()+"-"+dog.getAge()); } } } class Dog { private String name; private int age; public Dog(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; } } //假设      ,我们的程序员不小心添加了一只猫 arrayList.add(new Cat("招财猫",8));

那么 在使用增强for循环输出的时候向下转型时就会抛出异常:类型转换错误

使用传统方法问题的分析:

不能对加入到集合ArrayList中的数据进行约束(不安全) 遍历的时候          ,需要进行类型转换                ,如果集合中的数据量较大      ,对效率有影响

使用泛型来解决问题:

package li.generic; import java.util.ArrayList; @SuppressWarnings("all") public class Introduce_ { public static void main(String[] args) { //使用泛型 // 1. 当我们这样写的时候:ArrayList<Dog> 表示集合ArrayList中的元素是Dog类型 // 2. 如果编译器发现添加的类型不满足要求     ,就会报错 // 3.在遍历的时候                ,可以直接取出Dog类型而不是Object ArrayList<Dog> arrayList = new ArrayList<Dog>(); arrayList.add(new Dog("旺财",10)); arrayList.add(new Dog("发财",1)); arrayList.add(new Dog("小黄",5)); //假设           ,我们的程序员不小心添加了一只猫     ,就会报错 // arrayList.add(new Cat("招财猫",8)); System.out.println("====使用泛型===="); for (Dog dog:arrayList) { System.out.println(dog.getName()+"-"+dog.getAge()); } } } class Dog { private String name; private int age; public Dog(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; } } class Cat { private String name; private int age; public Cat(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; } } package li.generic; import java.util.ArrayList; @SuppressWarnings("all") public class Introduce_ { public static void main(String[] args) { //使用泛型 // 1. 当我们这样写的时候:ArrayList<Dog> 表示集合ArrayList中的元素是Dog类型 // 2. 如果编译器发现添加的类型不满足要求                ,就会报错 // 3.在遍历的时候           ,可以直接取出Dog类型,而不是Object ArrayList<Dog> arrayList = new ArrayList<Dog>(); arrayList.add(new Dog("旺财",10)); arrayList.add(new Dog("发财",1)); arrayList.add(new Dog("小黄",5)); //假设                ,我们的程序员不小心添加了一只猫                 ,就会报错 // arrayList.add(new Cat("招财猫",8)); System.out.println("====使用泛型===="); for (Dog dog:arrayList) { System.out.println(dog.getName()+"-"+dog.getAge()); } } } class Dog { private String name; private int age; public Dog(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; } } class Cat { private String name; private int age; public Cat(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; } }

泛型的好处:

编译时,检查添加元素的类型          ,提高了安全型

减少了类型转换的次数                 ,提高效率

如上面例子所示:不使用泛型的时候      ,Dog对象放到ArrayList里会先转成Object类型          ,在取出的时候还要再转换成Dog类型(Dog--加入-->Object--取出-->Dog)

使用了泛型                ,则放入和取出时都不需要类型转换      ,提高效率(Dog-->-Dog-->Dog)

不再提示编译警告

不添加@SuppressWarnings("all")编译器也不再警告

2.泛型介绍

泛型是一种可以表示数据类型的 数据类型

如下图:public class ArrayList<E>{} E 称为泛型

泛(广泛)型(类型)===>integer     ,String                ,Dog           ,……

泛型又称参数化类型     ,是jdk5.0出现的新特性                ,解决数据类型的安全性问题 在类声明或者实例化时只要指定好需要的具体类型即可 Java泛型可以保证如果程序在编译时没有发出警告           ,运行就不会产生ClassCastException异常          。同时,代码更加简洁          、健壮 泛型的作用是:可以在类声明时 通过一个标识 表示类中的某个属性                ,或者是某个方法的返回值的类型                 ,或者是参数类型

例子:

package li.generic; public class Generic03 { public static void main(String[] args) { Person<String> person = new Person<String>("jack"); person.showCalss();//class java.lang.String /* 可以这样理解:上面的Person类变为了 class Person{ String s; public Person(String s) { this.s = s; } public String f() { return s; } } */ Person<Integer> person1 = new Person<Integer>(100); person1.showCalss();//class java.lang.Integer /* 可以这样理解:上面的Person类变为了 class Person{ Integer s; public Person(Integer s) { this.s = s; } public Integer f() { 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 showCalss(){ System.out.println(s.getClass());//显示s的运行类型 } }

注意:E的数据类型在定义 Person 对象的时候指定      ,即在编译期间          ,就确定E是什么类型

泛型是一种可以表示数据类型的 数据类型

3.泛型的语法

3.1泛型的声明

interface 接口<T>{} 和class 类<K,V>{}//比如:List                 、ArrayList

说明:

1)其中                ,T,K,V不代表值      ,而是表示类型

2)任意字母都可以                 。常用T表示     ,是Type的缩写

3.2泛型的实例化

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

(1)List<String> strList = new ArrayList<String>() ;

(2)Iterator<Customer> iterator = customer.iterator();

3.3泛型使用举例

例子:泛型使用举例:

练习:

创建三个学生对象 学生对象放入到HashSet中使用 放入到HashMap中           ,要求Key是String name      ,Value就是学生对象 使用两种方法遍历

练习:

package li.generic; import java.util.*; public class GenericExercise { public static void main(String[] args) { //使用泛型的方法给HashSet放入三个学生对象 HashSet<Student> students = new HashSet<Student>(); students.add(new Student("jack", 18)); students.add(new Student("marry", 17)); students.add(new Student("link", 123)); //使用HashSet的增强for System.out.println("===使用HashSet的增强for==="); for (Student student : students) { System.out.println(student); } //使用泛型的方法给HashMap放入三个学生对象 HashMap<String, Student> hm = new HashMap<String, Student>(); hm.put("jack", new Student("jack", 18)); hm.put("lucy", new Student("lucy", 28)); hm.put("olin", new Student("olin", 16)); //迭代器 EntrySet System.out.println("===迭代器 EntrySet==="); Set<Map.Entry<String,Student>> entries = hm.entrySet(); Iterator<Map.Entry<String,Student>> iterator1 = entries.iterator(); while (iterator1.hasNext()) { Map.Entry<String, Student> next = iterator1.next(); System.out.println(next.getKey()+"-"+next.getValue()); } } } class Student { private String name; private int age; public Student(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; } @Override public String toString() { return "Student{" + "name=" + name + \ + ", age=" + age + }; } }

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

interface List<T>{} ,public class HashSet<E>{}..等等

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

看看下面语句是否正确?

List<Integer> list = new ArrayList<Integer>();//正确

List<int> list2 = new ArrayList<int>();//错误

在指定泛型具体类型后           ,可以传入该类型或者其子类类型

泛型使用形式

3.1 在实际的开发中,我们往往简写                ,编译器会进行类型推断,推荐使用下面的写法

ArrayList<Integer> list1 = new ArrayList<>();

3.2 泛型默认是Object类型                 ,即如果没有给泛型指定类型,默认就是Object:

ArrayList arrayList = new ArrayList();//等价为 ArrayList<Object> arrayList = new ArrayList<>();

例子:

package li.generic; import java.util.ArrayList; import java.util.List; public class GenericDetail { public static void main(String[] args) { //1.给泛型指向的数据类型要求是引用类型          ,不能是基本数据类型 List<Integer> list = new ArrayList<Integer>();//ok //List<int> list2 = new ArrayList<int>();错误 //2.因为 E指定了A类型                 ,构造器传入了 new A() Pig<A> aPig = new Pig<A>(new A());//将A类型赋给泛型E      ,说明Pig构造器可以接收的是A类型的对象 //在指定泛型具体类型后          ,可以传入该类型或者其子类类型 Pig<A> aPig2 = new Pig<A>(new B()); aPig.showClass();//class li.generic.A aPig2.showClass();//class li.generic.B // 3.泛型的使用形式 //在实际的开发中                ,我们往往简写      ,编译器会进行类型推断,推荐使用下面的写法 ArrayList<Integer> list1 = new ArrayList<>(); } } class A{} class B extends A{} class Pig<E>{ E e; public Pig(E e) { this.e = e; } public void showClass(){ System.out.println(e.getClass());//运行类型 } }

4.泛型课堂练习

定义Employee类

该类包括:private成员变量name     ,sal                ,birthday           ,其中birthday为MyDate类的对象;

为每一个属性定义getter      、setter方法;

重写toString方法输出name     ,sal                ,birthday;

MyDate类包括:private成员变量year           ,month,day      。并为为每一个属性定义getter          、setter方法;

创建该类的3个对象                ,并把这些对象放入ArrayList集合中(ArrayList需使用泛型来定义)                 ,对集合中的元素进行排序,并遍历输出:

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

练习:

package li.generic; import java.util.ArrayList; import java.util.Comparator; public class GenericHomework { public static void main(String[] args) { ArrayList<Employee> employees = new ArrayList<>(); employees.add(new Employee("tom", 20000, new MyDate(1980, 12, 11))); employees.add(new Employee("jack", 12000, new MyDate(2001, 12, 12))); employees.add(new Employee("tom", 50000, new MyDate(1980, 12, 10))); employees.sort(new Comparator<Employee>() { @Override public int compare(Employee o1, Employee o2) { // //比较name // int i = o1.getName().compareTo(o2.getName()); // if (i != 0) { // return i; // } // //如果name相同                ,就比较birthday-year // int yearMinus = o1.getBirthday().getYear()-o2.getBirthday().getYear(); // if (yearMinus !=0) { // return yearMinus; // } // //如果year相同      ,就比较month // int monthMinus = o1.getBirthday().getMonth()-o2.getBirthday().getMonth(); // if (monthMinus !=0) { // return monthMinus; // } // //如果month相同     ,就比较mday // return o1.getBirthday().getDay()-o2.getBirthday().getDay(); //比较name int i = o1.getName().compareTo(o2.getName()); if (i != 0) { return i; } //下面是对birthday的比较                ,因此           ,我们最好把日期的比较放到MyDate类完成 //封装后的维护性和复用性更好 return o1.getBirthday().compareTo(o2.getBirthday()); } }); for (Employee e : employees) { System.out.println(e); } } } class Employee { private String name; private int sal; private MyDate birthday; public Employee(String name, int 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 int getSal() { return sal; } public void setSal(int sal) { this.sal = sal; } public MyDate getBirthday() { return birthday; } public void setBirthday(MyDate birthday) { this.birthday = birthday; } @Override public String toString() { return "Employee{" + "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; } //如果month相同           ,就比较mday return day-o.getDay(); } }

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
腾讯电脑管家中我的手机是什么样的(腾讯电脑管家中我的手机是什么?) 七彩虹主板怎么调硬盘启动(七彩虹主板通过设置bios里的硬盘模式避免经常出现蓝屏的图文教程)