public class Generic01 {
public static void main(String[] args){
ArrayList arrayList = new ArrayList();
arrayList.add(new Dog("scott",4));
arrayList.add(new Dog("jack",5));
arrayList.add(new Dog("mary",6));
for(Object o : arrayList) {
Dog dog = (Dog) o;//获取对象的名字
System.out.println(dog.getName());
}
}
}
class Dog {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
public class Generic01 {
public static void main(String[] args){
ArrayList arrayList = new ArrayList<Dog>();
arrayList.add(new Dog("scott",4));
arrayList.add(new Dog("jack",5));
arrayList.add(new Dog("mary",6));
//arrayList.add(new Cat("招财猫",3));
for(Dog dog : arrayList) {
System.out.println(dog.getName());
}
}
}
不使用泛型:放入到ArrayList会先转成Object,在取出时,再转换成Dog;
使用泛型:放入和取出时,不需要类型转换;
不使用泛型 | 使用泛型 |
---|---|
放入到ArrayList会先转成Object,在取出时,再转换成Dog; | 放入和取出时,不需要类型转换; |
泛型 | Generic |
---|---|
参数的类型 | $1600 |
类中方法返回值的类型 | $12 |
属性的类型 | $1 |
定义Employee类
该类包括: private成员变量name, sal, birthday, 其中birthday 为 MyDate 类的对象;
为每一个属性定义 getter, setter 方法;
重写 toString 方法输出 name, sal, birthday
MyDate类包含: private成员变量month, day, year; 并为每一个属性定义 getter, setter 方法;
创建该类的 3 个对象, 并把这些对象放入到 ArrayList 集合中 (ArrayList 需使用泛型来定义), 对集合中的元素进行排序, 并遍历输出.
排序方式: 调用 ArrayList 的 sort 方法, 传入 Comparator 对象 [使用泛型], 先按照 name 排序, 如果 name 相同, 则按照生日日期的先后排序.[即: 定制排序
]
代码
MyDate类
/*
MyDate类包含: private成员变量month, day, year;
并为每一个属性定义 getter, setter 方法;
*/
public class MyDate {
private Integer year;
private Integer month;
private Integer day;
public MyDate(Integer year, Integer month, Integer day) {
this.year = year;
this.month = month;
this.day = day;
}
//setter, getter方法, toString方法
}
Employee类
/*
定义Employee类
1) 该类包括: private成员变量name, sal, birthday, 其中birthday 为 MyDate 类的对象;
2) 为每一个属性定义 getter, setter 方法;
3) 重写 toString 方法输出 name, sal, birthday
*/
public 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;
}
//setter, getter方法, toString方法
}
GenericExercise02
/*
创建该类的 3 个对象, 并把这些对象放入到 ArrayList 集合中
(ArrayList 需使用泛型来定义), 对集合中的元素进行排序, 并遍历输出.
排序方式: 调用 ArrayList 的 sort 方法, 传入 Comparator 对象 [使用泛型],
先按照 name 排序, 如果 name 相同, 则按照生日日期的先后排序.[即:定制排序]
*/
public class GenericExercise02 {
public static void main(String[] args) {
List<Employee> arrayList = new ArrayList<>();
arrayList.add(new Employee("tom", 45000, new MyDate(1999, 12, 21)));
arrayList.add(new Employee("tom", 35000, new MyDate(1999, 12, 25)));
arrayList.add(new Employee("mary", 40000, new MyDate(1998, 5, 12)));
System.out.println(arrayList);
//对员工雇员进行排序
arrayList.sort(new Comparator<Employee>() {
@Override
public int compare(Employee emp1, Employee emp2) {
//先按照 name 排序, 如果 name 相同, 则按照生日日期的先后排序.[即:定制排序]
//先对传入的参数进行验证
if (!(emp1 instanceof Employee && emp2 instanceof Employee)) {
return 0;
}
//比较名字
int i = emp1.getName().compareTo(emp2.getName());
if (i != 0) {
return i;
}
//下面是对MyDate类型的birthday对象的比较. 因此, 最好把这个比较, 放在MyDate类完成
//如果名字相同, 就比较birthday
int yearMinus = emp1.getBirthday().getYear() - emp2.getBirthday().getYear();
if (yearMinus != 0) {
return yearMinus;
}
//如果year相同, 就比较month
int monthMinus = emp1.getBirthday().getMonth() - emp2.getBirthday().getMonth();
if (monthMinus != 0) {
return monthMinus;
}
//如果month相同, 就比较day
int dayMinus = emp1.getBirthday().getDay() - emp2.getBirthday().getDay();
if (dayMinus != 0) {
return dayMinus;
}
return 0;
}
});
System.out.println("===排序后的结果===");
System.out.println(arrayList);
}
}
改进后:封装后代码复用性更高
MyDate 实现Comparable接口, 指定泛型, 实现compareTo方法
public class MyDate implements Comparable<MyDate> {
private Integer year;
private Integer month;
private Integer day;
@Override
public int compareTo(MyDate o) {把对year-month-day的比较放在这里
int yearMinus = this.year - o.getYear();
if (yearMinus != 0) {
return yearMinus;
}
//如果year相同, 就比较month
int monthMinus = this.month - o.getMonth();
if (monthMinus != 0) {
return monthMinus;
}
//如果month相同, 就比较day
int dayMinus = this.day - o.getDay();
if (dayMinus != 0) {
return dayMinus;
}
return 0;
}
}
GenericExercise02改进
//下面是对MyDate类型的birthday对象的比较. 因此, 最好把这个比较, 放在MyDate类完成
//如果名字相同, 就比较birthday
//封装后, 将来可维护性和复用性, 就大大增强
/*int yearMinus = emp1.getBirthday().getYear() - emp2.getBirthday().getYear();
if (yearMinus != 0) {
return yearMinus;
}
//如果year相同, 就比较month
int monthMinus = emp1.getBirthday().getMonth() - emp2.getBirthday().getMonth();
if (monthMinus != 0) {
return monthMinus;
}
//如果month相同, 就比较day
int dayMinus = emp1.getBirthday().getDay() - emp2.getBirthday().getDay();
if (dayMinus != 0) {
return dayMinus;
}
return 0;*/
return emp1.getBirthday().compareTo(emp2.getBirthday());
Comparator实现定制排序传送门
public class CustomGeneric {
public static void main(String[] args) {
//T是Double,R是String,M是Integer
Tiger<Double, String, Integer> tiger = new Tiger<>("john~~");
tiger.setT(3.2);//OK
System.out.println(tiger);
Tiger tiger1 = new Tiger("john");
//tiger.setT("yy");因为T是Object,"yy"是 Object子类,类型不对, 貌似字符串可以赋给Object类型
}
}
//1.Tiger后面有泛型,所以我们把Tiger 称为自定义泛型类
//2.T, R, M 泛型的标识符,一般是单个大写字母
//3.泛型的标识符可以有多个
//4.普通成员可以使用泛型 (属性、方法)
//5.使用泛型的数组,不能初始化
class Tiger<T, R, M> {
String name;
T t;//属性使用到泛型
M m;
R r;
public Tiger(String name) {
this.name = name;
}
//Type parameter 'T' cannot be instantiated directly
//T[] ts = new T[8];类型不能确定,无法分配空间,因为数组在new的时候不能确定T的类型,就无法在内存开辟空间
public Tiger(T t, M m, R r) {//构造器使用泛型
this.t = t;
this.m = m;
this.r = r;
}
//因为静态是和类相关的,在类加载时,对象还没有创建
//所以,如果静态方法和静态属性使用了泛型,JVM就无法完成初始化
/*static R r2;
public static void m1(M m) {//cannot be referenced from a static context
}*/
//方法使用泛型
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public M getM() {
return m;
}
public void setM(M m) {
this.m = m;
}
public R getR() {//返回类型可以使用泛型
return r;
}
public void setR(R r) {//方法使用到泛型
this.r = r;
}
}
基本语法:interface 接口名
/**
* 泛型接口使用说明
* 1.接口中,静态成员不能使用泛型
* 2.泛型接口的类型是在继承接口或者实现接口时实现的
*/
//1.在继承接口时,指定泛型接口的类型
interface IA extends IUsb<String, Double> {
}
//当我们去实现IA接口时,因为IA在继承IUsb接口时,指定了U为String,R为Double
// 因此在实现IUsb接口方法时,使用String替换U,Double替换R
class AA implements IA {
@Override
public Double get(String s) {
return null;
}
@Override
public void hi(Double aDouble) {
}
@Override
public void run(Double r1, Double r2, String u1, String u2) {
}
}
//2.实现接口时,直接指定泛型接口的类型
//给U指定了Integer, 给R指定了Float
//所以当实现IUsb接口方法时,会使用Integer替换U,Float替换R
class BB implements IUsb<Integer, Float> {
@Override
public Float get(Integer integer) {
return null;
}
@Override
public void hi(Float aFloat) {
}
@Override
public void run(Float r1, Float r2, Integer u1, Integer u2) {
}
}
//3.没有指定泛型,就默认为Object
//等价于class CC implements IUsb
class CC implements IUsb {
@Override
public Object get(Object o) {
return null;
}
@Override
public void hi(Object o) {
}
@Override
public void run(Object r1, Object r2, Object u1, Object u2) {
}
}
interface IUsb<U, R> {//U=Integer, R=Float
//接口中普通方法,可以使用泛型
R get(U u);
int n = 10;
//U name = "3e";静态成员不能使用泛型
void hi(R r);
void run(R r1, R r2, U u1, U u2);
//在jdk8以后,可以在接口中使用默认方法,在默认方法中可以使用泛型
default R method(U u) {
return null;
}
}
基本语法:修饰符[空格]
public class CustomMethodGeneric_ {
public static void main(String[] args) {
Car car = new Car();
//2. 当泛型方法被调用时,泛型类型就会确定,否则调用不起来;
car.fly("宝马",1200);//当调用方法时,传入参数,编译器就会确定类型
System.out.println("===========");
car.fly(2.2,1200);//当调用方法时,传入参数,编译器就会确定类型
System.out.println("===========");
//T:Sring, R:ArrayList
Fish<String, ArrayList> fish = new Fish<>();
//K:Float
fish.hello(new ArrayList(), 2.1f);
}
}
//1.泛型方法,可以定义在普通类中
class Car {//普通类
public void run() {//普通方法
}
//说明:泛型方法
// 就是泛型
// 提供给fly方法使用的
public <T, R> void fly(T t, R r) {//泛型方法
System.out.println(t.getClass());//String
System.out.println(r.getClass());//Integer
}
}
//2.泛型方法,也可以定义在泛型类中
class Fish<T, R> {//泛型类
public void run() {//普通方法
}
public <U, M> void fly(U u, M m) {//泛型方法
}
//说明
// hi()方法不是一个泛型方法
// 只是hi()方法使用了类声明的泛型
public void hi(T e) {
}
//泛型方法,可以使用类声明的泛型,也可以使用自己声明的泛型
public <K> void hello(R r, K k) {
System.out.println(r.getClass());//ArrayList
System.out.println(k.getClass());//Float
}
}
public class CustomMethodGenericExercise {
public static void main(String[] args) {
//T:String, R:Integer, M:Double
Apple<String, Integer, Double> apple = new Apple<>();
apple.fly(10);//泛型都是引用类型,所以10自动装箱,输出:Integer
apple.fly(new Dog());//输出:Dog
}
}
class Apple<T, R, M> {
public <E> void fly(E e) {
//.getClass():显示包名+类名;
//.getClass().getSimpleName():只显示类名
System.out.println(e.getClass().getSimpleName());
}
//public void eat(U u) {} //错误,U没有声明
public <U> void eat(U u) {} //改正
public void run(M m) {}
}
class Dog {}
通配符 | 作用 |
---|---|
List> c | 表示可以接收任意范型类型 |
List<? extends A> c | 表示可以接收A类或者A类的子类,规定泛型上限 |
List super A> c | 表示可以接收A类或者A类的父类(不限于直接父类),规定泛型下限 |
@SuppressWarnings({"all"})
public class GenericExtends {
public static void main(String[] args) {
//范型没有继承性
//List
//举例说明下面三个方法的使用;
List<Object> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<AA> list3 = new ArrayList<>();
List<BB> list4 = new ArrayList<>();
List<CC> list5 = new ArrayList<>();
//1.如果是 List> c, 可以接收任意的范型类型
printCollection1(list1);
printCollection1(list2);
printCollection1(list3);
printCollection1(list4);
printCollection1(list5);
//2.如果是 List extends AA> c, 可以接收AA或者AA的子类
//printCollection2(list1);
//printCollection2(list2);
printCollection2(list3);
printCollection2(list4);
printCollection2(list5);
//3.如果是 List super AA> c, 可以接收AA,AA的父类但不限于直接父类
printCollection3(list1);//正确
//printCollection3(list2);
printCollection3(list3);
//printCollection3(list4);
//printCollection3(list5);
}
public static void printCollection1(List<?> c) {
for (Object object : c) {//通配符,取出时就是Object
System.out.println(object);
}
}
public static void printCollection2(List<? extends AA> c) {
for (AA object : c) {
System.out.println(object);
}
}
//List> 表示任意范型类型都可以接收
//List extends AA> 表示的是上限,可以接收 AA或AA的子类
//List super AA> 表示的是下限,可以接收 AA或者AA的父类,不限于直接父类
public static void printCollection3(List<? super AA> c) {
for (Object object : c) {
System.out.println(object);
}
}
}
class AA {
}
class BB extends AA {
}
class CC extends BB {
}
shortcuts: Alt+Enter/option+Enter
可以直接运行一个方法,JUnit测试框架;
public class JUnit_ {
public static void main(String[] args) {
//new JUnit_().m1();
//new JUnit_().m2();
}
@Test
public void m1() {
System.out.println("m1()方法");
}
@Test
public void m2() {
System.out.println("m2()方法");
}
}
public class Homework01 {
public static void main(String[] args) {
}
@Test
public void test() {
//这里我们给泛型T指定的类型是User
DAO<User> userDAO = new DAO<>();
userDAO.save("No1", new User(1, 22));
userDAO.save("No2", new User(2, 23));
userDAO.save("No3", new User(3, 23));
List<User> list = userDAO.list();
userDAO.update("No3", new User(3, 18));
list = userDAO.list();
userDAO.delete("No3");
list = userDAO.list();
User user = userDAO.get("No2");
System.out.println(list);
System.out.println(user.getAge());
}
}
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);
}
public List<T> list() {
List<T> arrayList = new ArrayList<>();
Set<String> keySet = map.keySet();
Iterator<String> iterator = keySet.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
arrayList.add(get(key));
}
return arrayList;
}
public void delete(String id) {
map.remove(id);
}
}
class User {
private int id;
private int age;
public User(int id, int age) {
this.id = id;
this.age = age;
}
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;
}
@Override
public String toString() {
return "\nUser{" +
"id=" + id +
", age=" + age +
'}';
}
}