java泛型学习篇(一)
java泛型学习篇(一)
1 学习泛型前的传统思路
1.1 遍历集合中元素的方法
1.1.1 思路
①用foreach进行遍历
②把每个Object对象强转成所需类型
③打印其值
1.1.2 示例代码
import java.util.ArrayList;
public class Generic01 {public static void main(String[] args) {long startTime=System.currentTimeMillis();ArrayList arr= new ArrayList<>();for (int i = 0; i <100000; i++) {arr.add(Integer.valueOf(i));}for (Object o : arr) {//你想要使用Integer类型的方法必须强转,每一个数据都得这样,很麻烦Integer temp= (Integer) o;System.out.println(temp.intValue());}long endTime=System.currentTimeMillis();System.out.println("执行时长为(单位:毫秒): "+(endTime-startTime));}
}
1.1.3 运行截图
1.2 集合中若存放了非同类型的数据,并不会出现错误,出现的是运行时异常
1.2.1 示例代码
import java.util.ArrayList;public class Generic02 {public static void main(String[] args) {long startTime=System.currentTimeMillis();ArrayList arr= new ArrayList<>();for (int i = 0; i <100000; i++) {arr.add(Integer.valueOf(i));}arr.add("123");for (Object o : arr) {//你想要使用Integer类型的方法必须强转,每一个数据都得这样,很麻烦Integer temp= (Integer) o;System.out.println(temp.intValue());}long endTime=System.currentTimeMillis();System.out.println("执行时长为(单位:毫秒): "+(endTime-startTime));}
}
1.2.2 运行截图
2 学习泛型后的思路
2.1 遍历集合中元素的方法
2.1.1 思路
①在集合定义的时候加上泛型约束
②使用foreach循环打印值
2.1.2 示例代码
import java.util.ArrayList;
public class Generic03 {public static void main(String[] args) {long startTime=System.currentTimeMillis();ArrayList<Integer> arr= new ArrayList<>();for (int i = 0; i <100000; i++) {arr.add(Integer.valueOf(i));}for (Integer o : arr) {//你想要使用Integer类型的方法必须强转,每一个数据都得这样,很麻烦System.out.println(o.intValue());}long endTime=System.currentTimeMillis();System.out.println("执行时长为(单位:毫秒): "+(endTime-startTime));}
}
2.1.3 运行截图
2.2 集合中若存放了非同类型的数据,会出现错误,提示使用者必须改(不改必报错)
2.2.1 示例代码
import java.util.ArrayList;
public class Generic04 {public static void main(String[] args) {long startTime=System.currentTimeMillis();ArrayList<Integer> arr= new ArrayList<>();for (int i = 0; i <100000; i++) {arr.add(Integer.valueOf(i));}arr.add("123");for (Integer o : arr) {System.out.println(o.intValue());}long endTime=System.currentTimeMillis();System.out.println("执行时长为(单位:毫秒): "+(endTime-startTime));}
}
2.2.2 运行截图
a idea给出的错误提示
b 点击运行后
3 使用泛型好处
3.1 编译时,自动检查添加元素的类型,提高安全性,不是指定的类型是加不进去的
3.2 减少了类型转换次数和花费判断是否是一个类的实例的时间,有效提高了效率
4 泛型的理解
泛型是一种广泛的类型,是一种数据类型的数据类型,可以是Integer、String等
泛型又称之为参数化类型,是JDK5.0后出现的新特性(解决了数据类型的安全性问题)
泛型可以保证在编译时没有报错,运行时一定不会出现ClassCastException异常
泛型的作用:在类声明时通过一个标识符来表示类中某个属性的类型OR 方法返回值的类型 OR 参数类型
5 泛型的语法以及练习
5.1 语法
interface 接口<T>{}和 class类<k,v>{}
//T、K、V并不代表值,而是代表类型
//其实任意字母都可以,常用T表示,是Type的缩写
5.2 练习题目
5.2.1 题目内容
①创建5个教师对象
②把教师对象放入到HashSet中,要求约束为教师对象
③把教师对象放入到HashMap中,要求key为String类型,value为教师对象类型
④对②③这两种情况进行遍历,输出对应的结果即可
5.2.2 Teacher类代码
class Teacher{private String name;private int age;public Teacher(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Teacher{" +"name='" + name + '\\'' +", age=" + age +'}';}
}
5.2.3 示例代码
import org.apache.poi.ss.formula.functions.T;import java.util.*;public class GenericPractice {public static void main(String[] args) {//A.使用HashSetHashSet<Teacher> set = new HashSet<Teacher>();set.add(new Teacher("小明", 27));set.add(new Teacher("小洪", 32));set.add(new Teacher("小亮", 22));//使用增强for循环进行打印for (Teacher o :set) {System.out.println(o);}System.out.println("=========使用hashMap的方式===============");//B 使用HashMapHashMap<String, Teacher> h = new HashMap<>();h.put("xiaoming", new Teacher("小明", 27));h.put("xiaohong", new Teacher("小洪", 32));h.put("xiaoliang", new Teacher("小亮", 22));Set<Map.Entry<String, Teacher>> entries = h.entrySet();Iterator<Map.Entry<String, Teacher>> iterator = entries.iterator();while(iterator.hasNext()){Map.Entry<String, Teacher> next = iterator.next();System.out.println(next.getKey()+"-"+next.getValue());}}
}
class Teacher{private String name;private int age;public Teacher(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Teacher{" +"name='" + name + '\\'' +", age=" + age +'}';}
}
5.2.4 运行截图
6 泛型的注意事项
6.1 泛型一定是引用数据类型,不能是基本数据类型
ArrayList<Integer> arr= new ArrayList<>(); ✔
ArrayList<int> arr= new ArrayList<>(); ❌
6.2 在给泛型指定具体类型后,可以传入该类型或者其子类类型
import java.util.ArrayList;
public class Generic05 {public static void main(String[] args) {Pig<A> aPig = new Pig<A>(new A());//泛型是A类型,实参传过去的是A类型的子类型对象也是可以的Pig<A> bPig = new Pig<A>(new B());}
}
class A{}
class B extends A{}
class Pig<E>{E s;//E表示s的数据类型.该数据类型在定义A对象的时候指定,即在编译期间,就确定了public Pig(E s) {this.s = s;}
}
6.3 泛型的两种写法(推荐使用第二种)
6.3.1 左右两边全写
ArrayList<Integer> arr= new ArrayList<Integer>();
6.3.2 只写左边,不写右边
//实际开发中,往往采用这种
//编译器会进行类型推断,会默认把右边<>的类型和左边<>的类型保持一致
ArrayList<Integer> arr= new ArrayList<>();
6.4 如果没有给泛型指定数据类型,那么默认就是Object类型
ArrayList arr= new ArrayList();//本质上等价于下面这种写法
ArrayList<Object> arr= new ArrayList<Object>();
7 泛型的经典习题
7.1 题目内容
定义Employee类①该类中包含 private成员变量name,sal,birthday 其中birthday的类型为MyDate对象类型③为每个属性定义get和set方法③重写toString方法输出name,sal,birthday④定义有参构造
定义MyDate方法
①private成员变量month,day,year
②为每个属性定义get和set方法
③重写toString方法输出month,day,year
题目要求
创建Employee类的三个对象,并放入ArrayList集合中(泛型定义),对集合元素进行排序并输出
排序要求: 调用ArrayList的sort方法,传入Comparator对象
先按照name排序,如果name相同,就按照生日日期的先后进行排序
7.2 示例代码
7.2.1 Employee类
public class Employee{private String name;private double sal;private MyDate birthday;public Employee() {}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;}@Overridepublic String toString() {return "\\nEmployee{" +"name='" + name + '\\'' +", sal=" + sal +", birthday=" + birthday +'}';}
}
7.2.2 MyDate类
public class MyDate{private int month;private int day;private int year;public MyDate() {}public MyDate(int month, int day, int year) {this.month = month;this.day = day;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;}public int getYear() {return year;}public void setYear(int year) {this.year = year;}@Overridepublic String toString() {return "MyDate{" +"month=" + month +", day=" + day +", year=" + year +'}';}
}
7.2.3 GenericTest类
import java.util.ArrayList;
import java.util.Comparator;public class GenericTest {public static void main(String[] args) {ArrayList<Employee> arr = new ArrayList<Employee>();arr.add(new Employee("张三",2000,new MyDate(2,12,1999)));arr.add(new Employee("李四",4000,new MyDate(3,6,2005)));arr.add(new Employee("张三",8000,new MyDate(1,15,1970)));arr.sort(new Comparator<Employee>() {//先按照name排序,如果nam值相同,按照日期的先后顺序排序@Overridepublic int compare(Employee o1, Employee o2) {if(!(o1 instanceof Employee && o2 instanceof Employee)){System.out.println("类型不正确");return 0;}//比较nameint i = o1.getName().compareTo(o2.getName());if(i!=0){return i;}//如果name相同,比较的就是yearint yearMinus = o1.getBirthday().getYear() - o2.getBirthday().getYear();if(yearMinus!=0){return yearMinus;}//如果year相同,就比较monthint monthMinus = o1.getBirthday().getMonth() - o2.getBirthday().getMonth();if(monthMinus!=0){return monthMinus;}//如果month相同,就比较dayreturn o1.getBirthday().getDay()-o2.getBirthday().getDay();}});System.out.println("排序后的数组"+arr);}
}