一、引入
1、传统方法:
package generic_;
import java.util.ArrayList;
@SuppressWarnings({"all"})
public class Generic01 {
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());
}
//旺财-10
//发财-1
//招财-5
//如果不小心加入了一只猫,没有报错
arrayList.add(new Cat("加菲猫",8));
}
}
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;
}
}
2、使用泛型:
package generic_;
import java.util.ArrayList;
@SuppressWarnings({"all"})
public class Generic01 {
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));//报错
for(Dog dog:arrayList){
System.out.println(dog.getName()+"-"+dog.getAge());
}
//旺财-10
//发财-1
//招财-5
}
}
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;
}
}
3、 使用传统方法的问题分析:
(1)不能对加入到集合ArrayList中的数据类型进行约束(不安全)
(2)遍历的时候,需要进行类型转换,如果集合中的数据量较大,对效率有影响
4、泛型的好处
(1)编译时,检查添加元素的类型,提高了安全性
(2)减少了类型转换的次数,提高效率
·不使用泛型
Dog ->加入->object->取出->Dog//放入到Arraylist会先转成Object,在取出时,还需要转换成Dog
·使用泛型
Dog->Dog->Dog//放入时和取出时,不需要类型转换,提高效率
(3)不再提示编译警告
二、基本介绍:(“泛”:a whole group of things, not specific)
1、老韩理解:泛型=>Integer,String,Dog,可以表示数据类型的一种类型
(1)泛型又称参数化类型,是Jdk5.0出现的新特性,解决数据类型的安全性问题
(2)在类声明或实例化时只要指定好需要的具体的类型即可
(3)Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮
(4)泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型。
package generic_;
public class Generic02 {
public static void main(String[] args) {
Person<String> person=new Person<String>("韩顺平教育");
person.t();//class java.lang.String
//此时class Person<E>{}里面的所有的E都用String替换
Person<Integer> person1=new Person<Integer>(1);
person1.t();//class java.lang.Integer
//此时class Person<E>{}里面的所有的E都用Integer替换
}
}
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());//显示s的运行类型
}
}
2、泛型的语法:
(1)泛型的声明:
interface接口<T>和class类<K{}
//比如:List,ArrayList
说明:
1)其中,T,K,V不代表值,而是表示类型
2)任意字母都可以。常用T表示,是Type的缩写
(2)泛型的实例化:
要在类名后面指定类型参数的值(类型)。如:
1)List<String> strList= new ArrayList<String>0;
2) Iterator<Customer> iterator = customers.iterator0;
(3)
//我的代码:
package generic_;
import java.util.*;
@SuppressWarnings({"all"})
public class TestGeneric2 {
public static void main(String[] args) {
Student student=new Student();
Student student1=new Student();
Student student2=new Student();
HashSet hashSet=new HashSet();
hashSet.add(student);
hashSet.add(student1);
hashSet.add(student2);
HashMap hashMap = new HashMap();
hashMap.put("jack",student);
hashMap.put("tom",student1);
hashMap.put("smith",student2);
System.out.println("====================");
Set keyset=hashMap.keySet();
for (Object key :keyset) {
System.out.println(key+"-"+hashMap.get(key));
}
System.out.println("====================");
Set entrySet=hashMap.entrySet();
for (Object entry:entrySet) {
Map.Entry m=(Map.Entry)entry;
System.out.println(m.getKey()+"-"+m.getValue());
}
}
}
class Student<E>{
E student;
}
//====================
//tom-generic_.Student@4f3f5b24
//smith-generic_.Student@15aeb7ab
//jack-generic_.Student@27d6c5e0
//====================
//tom-generic_.Student@4f3f5b24
//smith-generic_.Student@15aeb7ab
//jack-generic_.Student@27d6c5e0
//老师的代码:
package generic_;
import java.util.*;
@SuppressWarnings({"all"})
public class TestGeneric2 {
public static void main(String[] args) {
HashSet<Student> students=new HashSet<Student>();
students.add(new Student("jack",18));
students.add(new Student("tom",28));
students.add(new Student("mary",19));
for (Student student :students) {
System.out.println(student);
}
HashMap<String, Student> hm = new HashMap<String, Student>();
hm.put("tom",new Student("tom",28));
hm.put("smith",new Student("smith",48));
hm.put("hsp",new Student("hsp",28));
//迭代器
/*自动填充的原因(hm.entrySet().var):
public Set<Map.Entry<K,V>> entrySet(){
Set<Map.Entry<K,V>> es;
return (es=entrySet)==null?(entrySet=new EntrySet()):es;
}
*/
Set<Map.Entry<String, Student>> entries = hm.entrySet();
/*自动填充的原因(entries.iterator().var):
public final Iterator<Map.Entry<K,V>> iterator(){
return new EntryIterator();
}
*/
Iterator<Map.Entry<String, Student>> iterator = entries.iterator();
System.out.println("===========================");
while (iterator.hasNext()) {
Map.Entry<String,Student> next=iterator.next();
System.out.println(next.getKey()+"-"+next.getValue());
}
}
}
//Student{name='mary', age=19}
//Student{name='jack', age=18}
//Student{name='tom', age=28}
//===========================
//tom-Student{name='tom', age=28}
//smith-Student{name='smith', age=48}
//hsp-Student{name='hsp', age=28}
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、泛型使用的注意事项和细节:
(1)interface List<T>{},public class HashSet<E>{}.等等
说明:T,E只能是引用类型,不能是基本数据类型
看看下面语句是否正确?:
List<Integer> list = new ArrayList<lnteger>();//对
List<int> list2 = new ArrayList<int>();//错
(2)在指定泛型具体类型后,可以传入该类型或者其子类类型
(3)泛型使用形式
List<Integer> list1 = new Arraylist<Integer>();
List<Integer> list2 = new ArrayList<>()://推荐,因为编译器会自动进行类型推断
(4)如果我们这样写List list3=new ArrayList();默认给它的泛型是[<E>E就是Object]
4、课堂练习题
//我的代码:
package generic_;
import java.util.ArrayList;
import java.util.Comparator;
@SuppressWarnings({"all"})
public class GenericExercise01 {
public static void main(String[] args) {
ArrayList<Employee> arrayList=new ArrayList<Employee>();
Employee jack = new Employee("jack", 10000, new MyDate(2000, 1, 1));
Employee tom = new Employee("tom", 20000, new MyDate(2001, 1, 1));
Employee smith = new Employee("smith", 30000, new MyDate(2002, 1, 1));
arrayList.add(jack);
arrayList.add(tom);
arrayList.add(smith);
arrayList.sort(new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
if(o1.getName().equals(o2.getName())){
if(o1.getBirthday()==o2.getBirthday()){
}else if(o1.getBirthday().getYear()==o2.getBirthday().getYear()){
if(o1.getBirthday().getMonth()==o2.getBirthday().getMonth()){
if(o1.getBirthday().getDay()==o2.getBirthday().getDay()){
return 0;
}else{
return o1.getBirthday().getDay()-o2.getBirthday().getDay();
}
}else{
return o1.getBirthday().getMonth()-o2.getBirthday().getMonth();
}
}else{
return o1.getBirthday().getYear()-o1.getBirthday().getYear();
}
}else{
return o1.getName().length()-o2.getName().length();
}
return 0;
}
});
System.out.println(arrayList);
//[Employee{name='tom', sal=20000.0, birthday=MyDate{year=2001, month=1, day=1}}, Employee{name='jack', sal=10000.0, birthday=MyDate{year=2000, month=1, day=1}}, Employee{name='smith', sal=30000.0, birthday=MyDate{year=2002, month=1, day=1}}]
}
}
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 "Employee{" +
"name='" + name + '\'' +
", sal=" + sal +
", birthday=" + birthday +
'}';
}
}
class 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 +
'}';
}
}
//老师的代码:
package generic_;
import java.util.ArrayList;
import java.util.Comparator;
@SuppressWarnings({"all"})
public class GenericExercise01 {
public static void main(String[] args) {
ArrayList<Employee> employees=new ArrayList<Employee>();
employees.add(new Employee("jack", 10000, new MyDate(2000, 1, 1)));
employees.add(new Employee("tom", 20000, new MyDate(2001, 1, 1)));
employees.add(new Employee("smith", 30000, new MyDate(2002, 1, 1)));
System.out.println("employees="+employees);
employees.sort(new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
//验证传入的参数
if(!(o1 instanceof Employee&&o2 instanceof Employee)){
System.out.println("类型不正确");
return 0;
}
//比较name
int i=o1.getName().compareTo(o2.getName());
if (i != 0) {
return i;
}
return o1.getBirthday().compareTo(o2.getBirthday());
}
});
System.out.println("=========排序后=========");
System.out.println("employees="+employees);
}
}
//employees=[
//Employee{name='jack', sal=10000.0, birthday=MyDate{year=2000, month=1, day=1}},
//Employee{name='tom', sal=20000.0, birthday=MyDate{year=2001, month=1, day=1}},
//Employee{name='smith', sal=30000.0, birthday=MyDate{year=2002, month=1, day=1}}]
//=========排序后=========
//employees=[
//Employee{name='jack', sal=10000.0, birthday=MyDate{year=2000, month=1, day=1}},
//Employee{name='smith', sal=30000.0, birthday=MyDate{year=2002, month=1, day=1}},
//Employee{name='tom', sal=20000.0, birthday=MyDate{year=2001, month=1, day=1}}]
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 '\n'+"Employee{" +
"name='" + name + '\'' +
", sal=" + sal +
", birthday=" + birthday +
'}';
}
}
class 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 +
'}';
}
//把对year-month-day的比较封装到MyDate类里面
public int compareTo(MyDate o){
//比较birthday的year
int yearMinus=year-o.getYear();
if (yearMinus != 0) {
return yearMinus;
}
//比较birthday的month
int monthMinus=month-o.getMonth();
if (monthMinus != 0) {
return monthMinus;
}
//比较birthday的day
return day-o.getDay();
}
}
5、自定义泛型(1)基本语法:
class类名<TR...>{//可以有多个泛型
成员
}
(2)注意细节:
1)普通成员可以使用泛型(属性、方法)
2)使用泛型的数组,不能初始化
3)静态方法中不能使用类的泛型
4)泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)
5)如果在创建对象时,没有指定类型,默认为Object
package generic_;
import java.util.ArrayList;
@SuppressWarnings({"all"})
public class CustomMethodGeneric {
public static void main(String[] args) {
Car car = new Car();
car.fly("宝马",100);//当调用方法时,传入参数,编译器就会确定类型
//class java.lang.String
//class java.lang.Integer
System.out.println("========================");
car.fly(300,100.1);//当调用方法时,传入参数,编译器就会确定类型
//class java.lang.Integer
//class java.lang.Double
System.out.println("========================");
Fish<String, ArrayList> fish = new Fish<>();
fish.hello(new ArrayList(),11.3f);
//class java.util.ArrayList
//class java.lang.Float
}
}
class Car{//普通类
public void run(){
}
//1、<T,R>就是泛型
//2、是提供给fly使用的,不是返回类型
public <T,R> void fly(T t,R r){//泛型方法
System.out.println(t.getClass());//自动装箱,String / Integer / Double...
System.out.println(r.getClass());//自动装箱,String / Integer / Double...
}
}
class Fish<T,R>{//泛型类
public void run(){
}
public <U,M> void eat(U u,M m){//泛型方法
}
//1、hi()方法不是泛型方法
//2、是hi()方法使用了类声明的泛型
//3、泛型方法 和 方法使用泛型 是不一样的
public void hi(T t){
}
//泛型方法,可以使用类声明的泛型,也可以使用自己声明泛型
public <K> void hello(R r,K k){//(R r,K k)中的R来自类的声明处,K来自方法的定义处
System.out.println(r.getClass());
System.out.println(k.getClass());
}
}
6、泛型的继承和通配符:
(1)泛型不具备继承性
List<Object> list= new ArrayList<String>()://对吗?
(2)<?>:支持任意泛型类型
(3)<?extends A>:支持A类以及A类的子类,规定了泛型的上限
(4)<?super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限
package generic_;
import java.util.ArrayList;
import java.util.List;
public class GenericExtends {
public static void main(String[] args) {
List<Object> list1=new ArrayList<>();
List<String> list2=new ArrayList<>();
List<A> list3=new ArrayList<>();
List<B> list4=new ArrayList<>();
List<C> list5=new ArrayList<>();
//List<?>
printCollection1(list1);
printCollection1(list2);
printCollection1(list3);
printCollection1(list4);
printCollection1(list5);
//List<? extends A>
printCollection2(list1);//报错
printCollection2(list2);//报错
printCollection2(list3);
printCollection2(list4);
printCollection2(list5);
//List<? super A>
printCollection3(list1);
printCollection3(list2);//报错
printCollection3(list3);
printCollection3(list4);//报错
printCollection3(list5);//报错
}
//方法一:
//List<?>表示任意的泛型类型都可以接受
public static void printCollection1(List<?> c){
for(Object object:c){//通配符,取出时,就是Object
System.out.println(object);
}
}
//方法二:
//<? extends A>:规定了泛型的上限,可以接受A或A子类
public static void printCollection2(List<? extends A> c){
for(Object object:c){
System.out.println(object);
}
}
//方法三:
//<? super A>子类类名A:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限
public static void printCollection3(List<? super A> c){
for(Object object:c){
System.out.println(object);
}
}
}
class A{
}
class B extends A{
}
class C extends B{
}
7、
//我的代码:
package generic_;
import java.util.List;
import java.util.Map;
import java.util.Set;
@SuppressWarnings({"all"})
public class Homework01 {
public static void main(String[] args) {
User jack = new User(1, 18, "jack");
User tom = new User(2, 19, "tom");
User smith = new User(3, 20, "smith");
}
}
class DAO<T>{
Map <String,T> stu;
public DAO(Map<String, T> stu) {
this.stu = stu;
}
public void save(String id, T entity){
System.out.println(stu.put(id,entity));
}
public T get(String id){
return stu.get(id);
}
public void update(String id,T entity){
System.out.println(stu.replace(id,entity));
}
public List <T> list(){
Set keySet=stu.keySet();
List list=null;
int size=stu.size();
for(int i=0;i<size;i++){
list.add(stu.get(keySet));
}
return list;
}
public void delete(String id){
System.out.println(stu.remove(id));
}
}
class User{
private int id;
private int age;
private String name;
public User(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
//老师的代码:
package generic_;
import innerclass.D;
import org.junit.Test;
import java.util.List;
import java.util.Map;
import java.util.Set;
@SuppressWarnings({"all"})
public class Homework01 {
public static void main(String[] args) {
User jack = new User(1, 18, "jack");
User tom = new User(2, 19, "tom");
User smith = new User(3, 20, "smith");
}
@Test
public void testList(){
DAO<User> dao=new DAO<>();
dao.save("001",new User(1,10,"jack"));
dao.save("002",new User(2,18,"king"));
dao.save("003",new User(3,38,"smith"));
List<User> list=dao.list();
System.out.println("list="+list);
System.out.println("==============================");
dao.update("003",new User(3,58,"milan"));
dao.delete("001");
list=dao.list();
System.out.println("list="+list);
System.out.println("==============================");
System.out.println("id==003:"+dao.get("003"));
}
}
//list=[User{id=1, age=10, name='jack'}, User{id=2, age=18, name='king'}, User{id=3, age=38, name='smith'}]
//==============================
//list=[User{id=2, age=18, name='king'}, User{id=3, age=58, name='milan'}]
//==============================
//id==003 User{id=3, age=58, name='milan'}
package generic_;
import java.util.*;
public class DAO<T>{
private Map<String,T> map=new HashMap<>();//搞清楚怎么定义这个成员变量的
public void save(String id, T entity){
map.put(id,entity);
}
public T get(String id){
return map.get(id);
}
public void update(String id,T entity){
map.put(id,entity);
}
//遍历map[k-v],将map的所有value(T entity),封装到ArrayList返回即可
public List<T> list(){
List<T> list = new ArrayList<>();
Set<String> keySet=map.keySet();
for (String key:keySet) {
list.add(map.get(key));
}
return list;
}
public void delete(String id){
map.remove(id);
}
}
package generic_;
public class User{
private int id;
private int age;
private String name;
public User(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
三、JUnit
1、为什么需要JUnit?
(1) 一个类有很多功能代码需要测试,为了测试,就需要写入到main方法中
(2) 如果有多个功能代码测试,就需要来回注销,切换很麻烦
(3)如果可以直接运行一个方法,就方便很多,并且可以给出相关信息,就好了
2、基本介绍:
(1)JUnit是一个Java语言的单元测试框架
(2)多数Java的开发环境都已经集成了JUnit作为单元测试的工具
3、操作:
(1)在要测试的方法上面写“@Test”
2、快捷键alt+enter,“Add 'JUnit5.4' to classpath”,选最新的就行了
3、下次用时就可以自动导入了,点击“小绿箭”就可以运行了