【JavaSE】泛型

1.为什么要有泛型

集合容器类在设计阶段/声明阶段不能确定这个容器到底存的是什么类型的对象,所以 在JDK1.5之前只能把元素类型设计Object,JDK1.5之后使用泛型来解决。因为这个时候除了元素的类型不确定,其他的部分是确定的,例如关于这个元素如何保存,如何管理等是确定的,因此此时 把元素的类型设计成一个参数,这个类型参数叫做泛型。Collection<E>,List<E>,ArrayList<E> 这个<E>就是类型参数,即泛型
 
泛型相比Object,能解决元素存储的安全性问题;解决获取数据元素时,需要类型强制转换的问题

public class Main {
    public static void main(String[] args){
        ArrayList list = new ArrayList();
        list.add(67);
        list.add(89);
        list.add(64);
        list.add(99);
        // 问题一:类型不安全
        list.add("78");
        for (Object o : list) {
            int score = (Integer) o;
            System.out.println(score);
        }
    }
}

 

2.在集合中使用泛型

1.集合接口或集合类在 jdk5.0时都修改为带泛型的结构
2.在实例化集合类时,可以指明具体的泛型类型
3.指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(方法、构造器、属性、内部类等)使用到类的泛型的位置,都指定完实例化时的类型,如: ArrayList<Integer> list = new ArrayList<Integer>(); list.add(E e) --> list.add(Integer integer)
4.泛型的类型必须是类,不能是基本数据类型。需要用到基本数据用包装类型替换
5.如果实例化时,没有指明泛型的类型,则默认为:java.lang.Object类型。

public class Main{
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(67);
        list.add(89);
        list.add(64);
        list.add(99);
        
        // list.add("67"); 编译时就会进行类型检查
        for (Integer integer : list) {
            System.out.println(integer); // 无需做类型强制转换
        }
    }
}
public class Main{
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<>(); // jdk8新特性,类型推断
        map.put("张三",56);
        map.put("李四",67);
        map.put("小红",89);
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        for (Map.Entry<String, Integer> entry : entries) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}

 

3.自定义泛型结构

自定义泛型类、泛型接口、泛型方法
 
(子类继承父类的泛型时指定类型, extends person<Integer>,子类实例化不用指定类型)
(子类继承父类的泛型时没有指定类型, extends person<T>,此时子类仍然是泛型类)
 
说明:
1.泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如:<E1,E2,E3>
2.泛型类的构造器如下:public GenericClass()。而这种是错误的:public GenericClass<E>(). 而是实例化时加上<>,person<Integer> p = new person<>();
3.实例化后,操作原来泛型位置的结构必须与指定的泛型类型一致。

4.泛型不同的引用不能相互赋值。
5.泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理,但不等价于Object。经验:泛型要使用一路都用。要不用,一路都不要用
6.静态结构中不能使用泛型,异常类中也不能使用泛型
7.不能够 T[] arr = new T[10],可以改为: T[] arr = (T[ ])new Object[10] ,new了Object数组,但是只能放T类型的数据
8.父类有泛型,子类可以选择保留、部分保留(Object)或不保留泛型(Object)也可以选择指定泛型类型

 

3.1 泛型类与接口

// 泛型类,泛型接口与泛型类相似。实现接口指定类型
class person<T> {

    int id;
    T t;
    String name;

    public person(int id, T t, String name) {
        this.id = id;
        this.t = t;
        this.name = name;
    }

    public void setT(T t) {
        this.t = t;
    }
}
public class Main{
	public static void main(String[] args){
		person p1 = new person(); //若实例化时没有指定,则为Object类型
		p1.setT(123);
		p1.setT("we");

		person<Integer> p2 = new person<>(); // 实例化时指明类的泛型
		p2.setT(45);
	}
}

 

3.2 泛型方法

boolean add(E e)不是泛型方法;<T> T[] toArray(T[] a)才是泛型方法,使用了不同的符号(T),与所在类是否带泛型结构无关 (方法形参类型不确定,在调用时指定类型)
并且在 返回类型前加上 <T>标识 此T不是类中的T,而是方法形参中的T

public class Main<E>{

	E e;

	public Main(E e){
		this.e = e;
	}
	
	public E get(){ // 不是泛型方法
		return e;
	}
	
	public static <T> List<T> v(T[] arr){ // 是泛型方法(可以是静态的,此T在调用时确定,不是是在对象实例化时确定)
		ArrayList<T> list = new ArrayList<>();
		...
		return list;
	}

	public static void main(String[] args){
        Integer[] arr = new Integer[]{1,2,3,4};
        List<Integer> v = v(arr); // 调用时指明类型,并返回相应类型的list

		System.out.println(v);
    }
}

 

4.泛型在继承上的体现

虽然类A是类B的父类,但G<A>和G<B>二者不具备父类关系,二者是并列关系(A<G>是B<G>的父类)

public class Main{
	public static void main(String[] args){
		Object obj = null;
		String str= null;
		obj = str; // 可以
	
		Object[] arr1 = null;
		String[] arr2 = null;
		arr1 = arr2; // 可以

		List<Object> list1 = null;
		List<String> lsit2 = null;
		lsit1 = list2; // 不可以,list1与 list2并没有子父类关系,都是 List类型。

		// AbStractList<String> list;
		List<String> list1 = null;
		ArrayList<String> list2 = null;
		list1 = list2; // 可以(继承或实现接口的关系都可以)
		// List<String> list = new ArrayList<>();
	}
}

 

5.通配符的使用

5.1 通配符 ?

? 【此时 list<?>相当于作为 List<String>和 List<Object>的父类使用】

public class Main{
	public static void main(String[] args){
		List<String> list1 = null;
		List<Object> list2 = null;
	
		List<?> list = null;
		list = list1;
		list = list2;

		print_list(list1);
		print_list(list2);
	}

	public void print_list(List<?> list){
       for (Object o : list) {
           System.out.println(o);
       }
	}
	
}

 

5.2 List<?>的读取

对于List<?>,不能够向其添加数据( ?不确定添加什么数据,但是什么对象都可以添加 null,所以可以添加null )
使用 Object o 读取 List<?>中的数据

public class Main{
	public static void main(String[] args){
		List<?> list = null;
		List<String> list1 = new ArrayList<>();
		list = list1;
		list.add("abc"); // 编译不通过
	}
}

 

5.3 含限制条件的通配符(<? extends/super class>)

1.通配符指定上限
上限extends: 使用时指定的类型必须是继承某个类,或者实现某个接口,即<=
2.通配符指定下限
下限super: 使用时指定的类型不能小于操作的类,即>=

举例
<? extends person>: 只允许泛型为 person及 person的子类的引用调用
<? super person>: 只允许泛型为 person及 person的父类的引用调用
<? extends person>: 只允许泛型为实现 Comparetor接口的实现类的引用调用
添加:
<? extends person>: 表示接受的类型小于等于person(负无穷到person中的一个),无法添加数据
<? super person>: 表示接受的类型大于等于person(person到正无穷中的一个),多态性可以添加person的及person的子类的数据

class person{

}
class student extends person{

}
public class Main{

	// 往下:最大范围是student ,要求使用student或以上的类型接受数据
    public void v(List<? extends student> list){ 
        for (student student : list) {
            System.out.println(student);
        }
    }

	// 往上:最大范围是Object,用Object类型接受,也只能用Object
    public void v1(List<? super student> list){ 
        for (Object o : list) {
            System.out.println(o);
        }
    }
}

 

6.泛型应用举例

public class BasicDao<T> {

    private QueryRunner qr = new QueryRunner();

    // DML操作方法的通用方法
    public int update(String sql, Object... parameters) {
        Connection connection = null;

        try {
            connection = JDBCUtils.getConnection();
            int update = qr.update(connection, sql, parameters);
            return update;
        } catch (SQLException e) {
            throw new RuntimeException();
        } finally {
            JDBCUtils.close(null, null, connection);
        }
    }
}
public class carDao extends BasicDao<car> {

    // 添加车辆
    public int addCar(car c) {
        String sql = "insert into car values (?,?,?,?,?,?,?)";
        return super.update(sql, c.getC_id(), c.getModel(), c.getColor(),
                c.getPrice(), c.getFactoryDate(), c.getManufacturer(), c.getState().toString());
    }

    // 删除车辆
    public int delCar(String c_id) {
        String sql = "delete from car where c_id = ?";
        return super.update(sql, c_id);
    }
}
public class customerDao extends BasicDao<customer>{

    // 添加客户
    public int addCustomer(customer cu){
        String sql = "insert into customer(cu_name,cu_telephone,level) values (?,?,?)";
        return super.update(sql, cu.getCu_name(), cu.getCu_telephone(), cu.getLevel().toString());
    }

    // 删除客户
    public int deleteCustomer(String cu_id){
        String sql = "delete from customer where cu_id = ?";
        return super.update(sql, cu_id);
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

り澄忆秋、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值