JavaSE------泛型(类型通配符、协变、逆变)、增强for循环、可变参数

泛型

泛型:Java集合有一个缺点,把一个对象丢进集合里去,集合就会忘掉这个数据的数据类型,当再次取出这个对象时,需要进行强制类型转换。为了解决这个问题,引入泛型这个概念。

泛型是一种推迟到创建对象,或者调用时才明确类型的特殊类型。
格式:   <数据类型>
好处:(1)把运行时期的问题提前到编译期间,否则当你输入不当类型,运行时才会报类转换异常
     (2)避免了强制转换,使用泛型 对象可以‘记住’输入类型
     (3)优化了黄色警告线
注意:泛型在运行期擦除,且不存在泛型类
专门讲一下为什么不存在泛型,举例:        
        List<Integer> integers = new ArrayList<>();
        List<String> strings = new ArrayList<>();
        System.out.println(integers.getClass() == strings.getClass());  

我们可以看到输出结果是TRUE,因为不管泛型的实际类型参数是什么,他们在运行时总有同样的类。不管为泛型形参传入那一种类型实参,对于Java来说,他们依然被当做同一个类处理,在内存中也只占一块内存空间.

泛型的类型通配符

当使用一个泛型类时,都应该为这个泛型传入一个类型实参。为了表示各中泛型 List 的父类,可以使用类型通配符:<?>。举例:

public void  test (List <?> c){
    for(int i=0;i<c.size();i++){
        System.out.printli(c.get(i));
        }
}   //  不管什么类型都可以调用,其类型为Object
设定类型通配符的上限
public  abstract class shape {
    public  abstract  void draw(Canvas c);
}
public  class Circle extends  shape{
    public  void  draw (Canvas c){
        System.out.println(c);
    }
}
public  class Canvas{
    public  void drawAll(List<? extends  shape> shapes){     // 同时画多个形状,使用被限制的泛型通配符
        for(shape s:shapes){
            s.draw(this);
        }
    }
}
List<? extends shape>就是个例子,这个未知类型一定是 shape的子类或本身,也就是说shape 就是这个通配符的上限

简而言之,这种指定通配符上限的集合,只能从集合中取元素

也称之为协变,对于协变的泛型只能调用返回类型作为返回值的方法。

注意:没有指定上限的泛型类,默认上限Object

设定通配符的下限

指定通配符下限的作用与上限刚好相反。通配符指定下限就是为了支持类型型变。举例: A <? super FOO>可以让 A A 赋给它,我们称之为逆变

逆变的泛型类型,只能调用泛型类型作为参数的方法。

public  abstract  class  demo {
      public static void main(String[] args) {
        // Comparator的实际类型是Treeset的父类,
          TreeSet<String> ts1 =new TreeSet< >(new Comparator<Object>(){
            public  int compare(Object fst,Object Snd){
                return  hashCode()>Snd.hashCode()?1:hashCode()<Snd.hashCode() ? -1:0;
            }
        });
        ts1.add("hello");
        ts1.add("wa");
        TreeSet<String> ts2 =new TreeSet< >(new Comparator<String>(){
            public  int compare(String first,String Second){
                return  first.hashCode()>Second.hashCode()?1:first.hashCode()<Second.hashCode() ? -1:0;
            }
        });
        ts2.add("hello");
        ts2.add("wa");
        System.out.println(ts1);
        System.out.println(ts2);
    }
通过使用通配符下限来定义Treeset构造器的参数,就可以传入可用参数,增加代码灵活性。
 

增强For循环

格式:  for(元素数据类型 变量:数组或集合){
            变量;
            }
举例:
       for (Integer b : integers) {
              System.out.println(b);
        }
注意:增强for循环内部使用的是迭代器,所以不能直接增删元素,线程异常,出现并发修改异常。

可变参数

格式:			修饰符 返回值类型 方法名(数据类型…  变量名){}
注意事项:
	这里的变量其实是一个数组
    如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个
举例:
   public static int add(int... a){
	int sum = 0 ;
	for(int s : a ){
		sum += s ;
	}
	return sum;
}

Array类的asList()方法

不一一赘述了,举个嵌套的例子:
    public static void main(String[] args) {
        Student s1 = new Student("张三",23);
        Student s2 = new Student("李四",23);
        Student s3 = new Student("王五",23);
        Student s4 = new Student("张三",18);
        Student s5 = new Student("李四",18);
        Student s6 = new Student("王五",18);
        ArrayList<Student> arrayList = new ArrayList<>();
        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
        ArrayList<Student> arrayList2 = new ArrayList<>();
        arrayList2.add(s4);
        arrayList2.add(s5);
        arrayList2.add(s6);
        List<ArrayList<Student>> arrayLists= new ArrayList<>();
        arrayLists.add(arrayList);
       arrayLists.add(arrayList2);
        for (ArrayList<Student> list : arrayLists) {
            System.out.println(list);
        }
    }
}
就是这么个例子,分两个班,班内各三个同学,遍历所有同学。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值