//自定义泛型类
public class Order {
String name;
int age;
//类的内部结构就可以使用类的泛型
T orderT;
//可以把泛型类看作是一个其他类,但实际上并非如此。只是这样方便去写代码
public Order() {
}
public Order(String name, int age, T orderT) {
this.name = name;
this.age = age;
this.orderT = orderT;
}
public T getOrderT() {
return orderT;
}
public void setOrderT(T orderT) {
this.orderT = orderT;
}
@Override
public String toString() {
return "Order{" +
"name='" + name + ''' +
", age=" + age +
", orderT=" + orderT +
'}';
}
}
//测试自定义泛型类
@Test
public void test4(){
//如果定义了泛型类,实例化没有指明类的泛型,则认为此泛型类型为Object类型
//要求:如果定义了类是带泛型的,建议在实例化时要指明类的泛型。
Order order = new Order();
order.setOrderT(123);
order.setOrderT("ABC");
//建议:实例化时指明类的泛型
Order order1 = new Order<>("AA",1001,"AA:World");
order1.setOrderT("AA:Hello");
}
//泛型方法举例
public class Order {
//泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系。
//换句话说,泛型方法所属的类是不是泛型类都没有关系。
//泛型方法,可以声明为静态的。原因:泛型参数是在调用方法时确定的。并非在实例化类时确定。
public List copyFromArrayToList(E[] arr){
ArrayList list = new ArrayList<>();
for (E e:
arr) {
list.add(e);
}
return list;
}
}
//可以声明为静态方法
//测试泛型方法
@Test
public void test7(){
Order order = new Order<>();
Integer[] arr = new Integer[]{1,2,3};
//泛型方法在调用时,指明泛型参数的类型。这个类型与类的泛型无关
List list = order.copyFromArrayToList(arr);
System.out.println(list);
}
//DAO:data(base) access object。 数据访问对象
public class DAO {//表的共性 *** 作的DAO
//添加一条记录
public void add(T t){
}
//删除一条记录
public boolean remove(int index){
return false;
}
//修改一条记录
public void update(int index,T t){
}
//查询一条记录
public T getIndex(int index){
return null;
}
//查询多条记录
public List getForList(int index){
return null;
}
//泛型方法
//举例:获取表中一共有多少条记录?(返回long或int) 获取最大的员工入职时间?(返回Date)
public E getValue(){
return null;
}
}
public class Customer {//此类对应数据库中的customer表
}
public class CustomerDAO extends DAO{//只能 *** 作某一个表的DAO
}
public class Student {//此类对应数据库中的Student表
}
public class StudentDAO extends DAO{//只能 *** 作某一个表的DAO
}
public class DAOTest {
@Test
public void test1(){
CustomerDAO dao1 = new CustomerDAO();
dao1.add(new Customer());
List forList = dao1.getForList(10);
StudentDAO dao2 = new StudentDAO();
dao2.add(new Student());
List list = dao2.getForList(10);
}
}
泛型在继承方面的体现
泛型在继承方面的体现:
虽然类A是类B的父类,但是G 和 G 二者不具备子父类关系,二者是并列关系。补充:类A是类B的父类,A
是 B
的父类
由于虽然类A是类B的父类,但是G 和 G 二者不具备子父类关系,二者是并列关系,这种关系的存在导致不能使用多态性,对于一些共同的方法还需要单独定义。这对我们来说很不方便,增加了代码的冗余。
为此提出了通配符,找到G 和 G的共同父类,也就是说类A是类B的父类,G 和 G 是没有关系的,二者共同的父类是:G>
2.通配符的使用
通配符:?
@Test
public void test10(){
List list1 = null;
List list2 = null;
//利用通配符"?" 可以找到List、List的共同父类
List> list = null;
list = list1;
list = list2;
print(list1);
print(list2);
}
//利用通配符"?" 可以找到List、List的共同父类,减少代码的冗余
public void print(List> list){
Iterator> iterator = list.iterator();
while (iterator.hasNext()){
//不管你返回什么类型但总归是Object的一个子类。
Object obj = iterator.next();
System.out.println(obj);
}
}
使用通配符后数据的读取和写入要求
写入数据(添加):对于List>就不能向其内部添加数据。除了添加null之外。
读取数据(获取):允许读取数据,读取的数据类型为Object
List list3 = new ArrayList<>();
list3.add("AA");
list3.add("BB");
list3.add("CC");
list3.add("DD");
list = list3;
//添加(写入):对于List>就不能向其内部添加数据。
//除了添加null之外。
//解释:由于不确定类型,有可能你添加的数据类型比要求的数据类型还大,根据多态性,就会导致出错,所以不能添加数据
// list.add("aa");
// list.add("?");
list.add(null);
//获取(读取):允许读取数据,读取的数据类型为Object
Object o = list.get(0);//不管返回什么类型,但总归是Object的子类
System.out.println(o);
在 “通配符 ? 的使用” 这一段落中示例代码中遍历 *** 作就是读取数据。
有限制条件的通配符的使用
3.有限制条件的通配符的使用
? 可以类比 (-∞,+∞);? extends A表示(-∞,A] ;? super A 表示[A,+∞)
总结:
? extends A :
G<? extends A> 可以作为G 和 G 的父类,其中B是A的子类
? super A:
G<? super A> 可以作为G 和 G 的父类,其中B是A的父类
@Test
public void test11(){
List extends Person> list1 = null;
List super Person> list2 = null;
List list3 = null;
List list4 = null;
List list5 = null;
//说明 ? extends Person 表示小于等于Person
list1 = list3;
list1 = list4;
// list1 = list5;//编译不通过
//说明 ? super Person 表示大于等于Person
// list2 = list3;//编译不通过
list2 = list4;
list2 = list5;
//有限制条件的通配符在写入和读取数据
//读取数据:
list1 = list3;
Person p = list1.get(0);
//编译不通过
// Student s = list1.get(0);
list2 = list4;
Object obj = list2.get(0);
//编译不通过
// Person obj = list2.get(0);
//写入数据时
//编译不通过
// list1.add(new Student());因为 ? extends Person 表示小于等于Person,数据类型有可能比Student还小
//? super Person 表示大于等于Person,所以数据类型也大于等于Person,根据多态可以添加比其小的。
list2.add(new Person());
list2.add(new Student());
}
注意有限制条件的通配符在写入和读取数据时跟之前有些许不同。
根据面向对象知识分析:
? extends Person读取数据时返回值可以缩小Person
? super Person读取数据时返回值是Object
? extends Person不可以写入数据(除了null)
? super Person可以写入Person类及其子类的对象。
练习
定义个泛型类 DAO,在其中定义一个 Map 成员变量,Map 的键为 String 类型,值为 T 类型。 定义一个 User 类: 该类包含:private 成员变量(int 类型) id,age;(String 类型)name。 定义一个测试类: 创建 DAO 类的对象, 分别调用其 save、get、update、list、delete 方法来 *** 作 User 对象, 使用 Junit 单元测试类进行测试。
public class DAO {
//后面的方法中用到了map,所以要先初始化
private Map map = new HashMap<>();
//保存 T 类型的对象到 Map 成员变量中
public void save(String id,T entity){
map.put(id,entity);
}
//从 map 中获取 id 对应的对象
public T get(String id){
return map.get(id);
}
//替换 map 中key 为id 的内容,改为 entity 对象
public void update(String id,T entity){
//需要先判断是否存在这个id
if (map.containsKey(id)){
map.put(id,entity);
}
}
//返回 map 中存放的所有 T 对象
public List list(){
//解决思路,通过遍历,将数据取出来放入数组List
Collection values = map.values();
Iterator iterator = values.iterator();
ArrayList list = new ArrayList<>();
while (iterator.hasNext()){
T next = iterator.next();
list.add(next);
}
return list;
}
//删除指定 id 对象
public void delete(String id){
map.remove(id);
}
}
public class User {
private int id;
private String name;
public User() {
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + ''' +
'}';
}
//User作为value,应该重新equals()方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return id == user.id && Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}
public class DaoTest {
public static void main(String[] args) {
DAO dao = new DAO<>();
dao.save("1001",new User(1001,"周杰伦"));
dao.save("1002",new User(1002,"汪苏泷"));
dao.save("1003",new User(1003,"许嵩"));
User user = dao.get("1001");
System.out.println(user);
dao.update("1003",new User(1003,"毛不易"));
dao.delete("1003");
List list = dao.list();
Iterator iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
评论列表(0条)