JavaSE进阶 | 泛型机制和增强for循环

发布于:2023-02-17 ⋅ 阅读:(716) ⋅ 点赞:(0)

目录

🥅初识泛型机制

🥅自定义泛型

🥅增强for循环(foreach)


🥅初识泛型机制

⭐️JDK5.0之后推出的新特性:泛型
⭐️泛型这种语法机制,只在程序编译阶段起作用,只是给编译器参考的(运行阶段泛型没用)
⭐️使用了泛型优点是什么?
第一:集合中存储的元素类型统一了。
第二:从集合中取出的元素类型是泛型指定的类型,不需要进行大量的“向下转型”!

⭐️泛型的缺点是什么?
导致集合中存储的元素缺乏多样性!

❤️例1:泛型的用法

对于泛型就相当于范围缩小了,对于一个集合我们可以加进去任何类型的元素;当我们调用迭代器的next()方法时,取出来的类型实际上是Object类型;我们去调用类中的方法就需要向下转型;但是如果我们指定一个泛型的范围,就不需要向下转型,存取其它范围的类型就会报错!我们来通过一个例题感受一下吧!

package com.bjpowernode.javase.collection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


public class GenericTest01 {
    public static void main(String[] args) {
        //1.不使用泛型
        List mylist = new ArrayList();

        //1.1.创建对象
        Cat c = new Cat();
        Bird b = new Bird();

        //1.2.增加对象到集合当中
        mylist.add(c);
        mylist.add(b);

        //1.3.获取迭代器,遍历集合调用move方法
        Iterator it = mylist.iterator();
        while(it.hasNext()){
            // 取出来的对象默认是Object类型;Object里面没有move()方法
            Object obj = it.next();
            // 向下转型
            if(obj instanceof Animal){
                Animal animal = (Animal)obj;
                animal.move();
            }
        }


        //2.使用泛型
        // 使用泛型List<Animal>之后,表示List集合中只允许存储Animal类型的数据。
        // 用泛型来指定集合中存储的数据类型。
        List<Animal> mylist = new ArrayList<Animal>();

        //2.1.创建对象
        Cat c = new Cat();
        Bird b = new Bird();

        //2.2.增加元素
        mylist.add(c);
        mylist.add(b);

        //2.3.获取迭代器,遍历调用move方法
        // 这个表示迭代器迭代的是Animal类型。
        Iterator<Animal> it = mylist.iterator();
        while(it.hasNext()){
            // 使用泛型<Animal>,取出来的元素是Animal类型
           Animal animal = it.next();
           // 不需要向下转型,直接调用
            animal.move();
          //  但是调用子类中特有的方法还是需要向下转型,只是方便了一个环节
          if(animal instanceof Cat){
              Cat cat = (Cat)animal;
              cat.catchMouse();
          }
          if(animal instanceof Bird){
              Bird bird = (Bird)animal;
              bird.fly();
          }

        }
    }

}

class Animal {
    // 父类自带方法
    public void move(){
        System.out.println("动物在移动!");
    }
}

class Cat extends Animal {
    // 特有方法
    public void catchMouse(){
        System.out.println("猫抓老鼠!");
    }
}

class Bird extends Animal {
    // 特有方法
    public void fly(){
        System.out.println("鸟儿在飞翔!");
    }
}

❤️例2:自动类型推断

JDK8之后引入了:自动类型推断机制。(又称为钻石表达式)

package com.bjpowernode.javase.collection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class GenericTest02 {
    public static void main(String[] args) {
        // ArrayList<这里的类型会自动推断>(),前提是JDK8之后才允许。
        List<Animal> myList = new ArrayList<>(); //自动类型推断

        //添加对象到集合
        myList.add(new Animal());
        myList.add(new Cat());
        myList.add(new Bird());

        //遍历
        Iterator<Animal> iterator = myList.iterator();
        while(iterator.hasNext()){
            Animal an = iterator.next();
            an.move();
        }

        // 在比如:只存String类型的集合
        List<String> str = new ArrayList<>(); //自动类型推断
        str.add("http://www.126.com");
        str.add("http://www.baidu.com");
        str.add("http://www.bjpowernode.com");
        //str.add(new String(123)); //错误,类型不匹配

        System.out.println(str.size()); //3

        // 遍历
        Iterator<String> it2 = str.iterator();
        while(it2.hasNext()){
            // 如果没有使用泛型,还需要判断是不是一个String
            Object obj = it2.next();
            if(obj instanceof String){
                String ss = (String)obj;
                ss.substring(7);
            }
             
            // 使用泛型表达式,直接通过迭代器获取了String类型的数据
            String s = it2.next();
            // 直接调用String类的substring方法截取字符串。
            String newString = s.substring(7);
            System.out.println(newString);
        }


    }
}

🥅自定义泛型

⭐️有了上面对泛型的理解,我们能让自己定义的类也具有泛型这种特性吗?下面让我们一起来自定义泛型!
⭐️自定义泛型的时候,<> 尖括号中的是一个标识符,随便写。
⭐️java源代码中经常出现的是:<E>和<T> 都是出现在类上定义
①E是Element单词首字母;使用E一般出现在方法的参数列表里。
②T是Type单词首字母;一般出现在方法的返回值类型上。

package com.bjpowernode.javase.collection;
//自定义泛型
public class GenericTest03<E> { //E只是标识符,随便写,一般写E或者T

    //提供一个方法,注意里面参数
    public void doSome(E e){
        System.out.println(e);
    }
    //程序入口
    public static void main(String[] args) {
        //1、创建对象,假如这个方法只能调用用String类型
        GenericTest03<String> gt = new GenericTest03<>(); //自动类型推断
        //gt.doSome(10); //类型不匹配
        gt.doSome("abc"); //这个方法传参只能跟String类型

        // 创建对象,假如这个方法只能调用用Integer类型
        GenericTest03<Integer> gt2 = new GenericTest03<>();
        //gt2.doSome("abc"); //类型不匹配
        gt2.doSome(100); //自动装箱

        //2、定义一个方法,返回的类型要与类的泛型类型保持一致
        MyIterator<String> mt = new MyIterator<>();
        String str = mt.get(); //返回类型只能是String

        MyIterator<Animal> mt2 = new MyIterator<>();
        Animal an = mt2.get(); //返回类型只能是Animal

        //3、定义了泛型我们不用,参数就是Object类型
        GenericTest03 gt3 = new GenericTest03();
        gt3.doSome(new Object()); //参数就是Object类型

    }
}
class MyIterator<T>{
    public T get(){
        return null;
    }
}

🥅增强for循环(foreach)

⭐️JDK5.0之后推出了一个新特性:叫做增强for循环,或者叫做foreach

⭐️我们已经学习了for循环,那么什么又是增强for循环呢?我们先看语法:

for(元素类型 变量名 : 数组或集合){
      System.out.println(变量名);
}

 ⭐️增强for循环的缺点没有下标!

package com.bjpowernode.javase.collection;

public class ForEachTest01 {
    public static void main(String[] args) {
        // 1.定义一个数组
        int[] arr = {22,3,9,5,6,8};
        // 2.遍历打印(普通for循环)
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        // 3.增强for循环
        for(int i:arr){
            // foreach有一个缺点:没有下标。在需要使用下标的循环中,不建议使用增强for循环。
            // i就是数组中的元素(数组中的每一个元素)
            System.out.println(i);
        }
    }

}

❤️例:集合使用foreach

对于有下标的集合,我们现在就学到了三种打印方式:迭代器、利用下标、foreach

package com.bjpowernode.javase.collection;

import java.util.*;

//集合使用foreach
public class ForEachTest02 {
    public static void main(String[] args) {
        // 创建List集合
        List<String> strList = new ArrayList<>();

        // 增加元素
        strList.add("hello");
        strList.add("world");
        strList.add("kitty");

        //1. 遍历,使用迭代器
        Iterator<String> it = strList.iterator();
        while(it.hasNext()){
            System.out.print(it.next()+" ");
        }
        System.out.println();

        //2. 使用下标方式
        for (int i = 0; i < strList.size(); i++) {
            System.out.print(strList.get(i)+" ");
        }
        System.out.println();

        //3. 使用foreach
        // 因为泛型使用的是String类型,所以是:String s
        for (String s:strList) {
            System.out.print(s+" ");
        }
    }

}

本文含有隐藏内容,请 开通VIP 后查看