泛型讲解-11月10日讲课内容

2020-11-10T21:43:00

泛型

泛型接口

案例代码1

interface USB {}

class Mouse implements USB {}

class Keyboard implements USB {}

interface PC<T> {
    // 接口中的常量不能使用泛型
    
    T use(T t);
}

/*
 *  实现类实现接口时不指定泛型类型,
 *  需要在创建对象时明确
 */
class MyPC<T> implements PC<T> {
    @Override
    public T use(T t) {
        return t;
    }
}

/*
 * 实现类实现接口时,接口中泛型的类型已经明确,
 * 实现的方法也是明确的
 */
class YourPC implements PC<Mouse> {
    @Override
    public Mouse use(Mouse t) {
        return t;
    }
}

public class GenericityInterfaceDemo {
    public static void main(String[] args) {
        // 创建对象时明确泛型的类型
        MyPC<Keyboard> myPC = new MyPC<Keyboard>();
        
        Keyboard keyboard = myPC.use(new Keyboard());

        System.out.println(keyboard);
        
        System.out.println("-----------------");
        
        // 声明类时已经明确泛型的类型,所以这里的类型已经是明确的
        YourPC yourPC = new YourPC();
        
        Mouse mouse = yourPC.use(new Mouse());
        
        System.out.println(mouse);
    }
}

案例代码2

/**
 * 自定义一个比较器接口
 * @param <T> 泛型
 */
interface Comparable<T> {
    /**
     * 这是一个比较方法,实现类应该实现这个方法以达到比较的目的
     * 
     * @param t 传入被比较的对象
     * @return 负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。
     */
    public abstract int compareTo(T t);
}
/**
 * 自定义父类,实现比较器接口
 */
class Father implements Comparable<Father>{
    private String name;
    private int age;
    
    // Constrator、setters、getters
    
    @Override
    public int compareTo(Father f) {
        return this.age - f.age;
    }
}

public class GenericityInterfaceDemo {
    public static void main(String[] args) {
        Father father1 = new Father("小明父亲", 30);
        Father father2 = new Father("小红父亲", 29);
        
        if (father1.compareTo(father2) < 0) {
            System.out.println("小红父亲年长:" + father2.getAge());
        } else {
            System.out.println("小明父亲年长:" + father1.getAge());
        }
    }
}

【注意】

1、接口中的成员变量不能使用泛型,因为static、final
2、泛型接口的实现类可以指定泛型的类型,也可以不指定,如果在实现类中明确了数据类型,创建对象时就不需要再进行明确

泛型通配符

在泛型中,? 表示未知类型,被称为通配符。通配符可以在各种情况下使用:可以作为形式参数、成员变量、局部变量的类型,也可以作为返回值类型。但是,通配符不能用于泛型方法调用、泛型类实例创建对象或者父类的类型实际参数

表示全部类型,类似Object。区别于T,T只是占位符,而 ?是数据类型

<?>

【使用场景】

1、当一个方法可以用Object类提供的功能来实现时,泛型通配符是使用的

2、若代码使用了泛型类中的方法,而这些方法又是不依赖于参数化类型的,可以使用泛型通配符

案例代码

class Grade<T> {
    private T t;
    
    // Constructor、setter and getter、toString
    
    public void show() {
        System.out.println("show" + this);
    }
}

class School {
    // 这里使用泛型通配符,表示可以传入任意类型
    public void showGrade(Grade<?> grade) {
        grade.show();
    }
}

public class GenericityWildCardDemo {
    public static void main(String[] args) {
        School school = new School();
        
        school.showGrade(new Grade<Student>(new Student()));
        school.showGrade(new Grade<Teacher>(new Teacher()));
    }
}

泛型上限

表示以T为父类的所有子类(包括父类)

<? extends T>

泛型下限

表示以E为子类的所有父类(包括子类)

<? super E>

案例代码

class School {
    public void showGrade(Grade<?> grade) {
        grade.show();
    }
    
    // 泛型上限,Person类本身及其子类都可以使用
    public void showExtends(Grade<? extends Person> grade) {
        System.out.println(grade);
    }
    
    // 泛型下限,Person类本身及其父类都可以使用
    public void showSuper(Grade<? super Person> grade) {
        System.out.println(grade);
    }
}

public class GenericityWildCardDemo {
    public static void main(String[] args) {
        School school = new School();
        
        school.showGrade(new Grade<Student>(new Student()));
        school.showGrade(new Grade<Teacher>(new Teacher()));
        
        // 泛型上限,可以声明子类的类型
        school.showExtends(new Grade<Student>());
        // 泛型下限,可以声明父类的类型
        school.showSuper(new Grade<Object>());
    }
}

泛型推断

JDK1.7新特性,可以省略实例化对象时尖括号内的类型

案例代码

public class GenericityInferDemo {
    public static void main(String[] args) {
        // 泛型推断
        Grade<Student> grade = new Grade<>();
        
        // 得到对应的类型
        Student student = grade.getT();
    }
}

总结

1、泛型就是泛化的类型,本质是参数化类型,是jdk1.5引入的新特性,用在类、接口和方法上,即泛型类,泛型接口和泛型方法

2、为了解决利用继承Object来实现通用性导致的强制类型转换和可能发生的类型转换异常的问题。

3、泛型的好处是确保了编译时期的类型安全,和避免了强制类型转换的麻烦

4、缺陷是因为泛型使用了类型擦除机制,jvm运行之前会将泛型信息擦除掉,这样做是为了兼容jdk1.5之前的代码,但是也会导致通过反射可以跳过泛型的问题,因为运行期间并没有泛型的限制

5、泛型通配符?代表任意类型,泛型上限<? extends T>,泛型下限<? super T>

6、jdk1.7新特性泛型推断,声明变量时定义过泛型得话,在实例化对象时可以省略类型,但是还要加<>,否则还是原类型

集合

学习要求

抄!!!!!!!!!

集合框架

interface Collection<E> Java中所有集合的总接口
--| interface List<E> List接口,数据存储可重复,有序。
----| class ArrayList<E> 
    重点 可变长数组
----| class LinkedList<E> 
    重点 双向链表模式
----| class Vector<E>
    线程安全的可变长数组
--| interface Set<E> Set接口,数据存储不可以重复,无序
----| HashSet<E> 
    底层存储数据的结构是一个哈希表,存储效率,查询效率极高!!!
----| TreeSet<E> 
    底层存储数据的结构是一个平衡二叉树结构,要求数据必须有比较方式!!!
集合框架关系图

collection 接口

boolean add(E e)
    添加当前集合约束的指定数据类型到当前集合中
    
boolean addAll(Collection<? extends E> c);
    添加另一个集合到当前集合中,要求添加集合中保存的元素必须是当前集合中保存
    元素本身或者其子类对象 【泛型的上限】
    class Dog extends Animal
    class Cat extends Animal
    class Tiger extends Animal

案例代码

public class Test {
    public static void main(String[] args) {
        Collection<String> collection1 = new ArrayList<String>();
        Collection<String> collection2 = new ArrayList<String>();
        
        collection1.add("Java");
        collection1.add("Hello");
        
        collection2.add("Java");
        collection2.add("Hello");
        collection2.add("World");
        
        System.out.println(collection1);    // [Java, Hello]
        
        collection1.addAll(collection2);        
        System.out.println(collection1);    // [Java, Hello, Java, Hello, World]
    }
}
当前页面是本站的「Baidu MIP」版。发表评论请点击:完整版 »