【151天】尚学堂高淇Java300集视频精华笔记(117-118)

一点小心得

  1. 面对完全没有头绪的工作,只要开始第一步,神奇的事情就会发生,编程这件事,这一点体现的淋漓尽致,只有一行动,思路就会泉涌而来。

  2. 未来我计划以3天为一个周期,将剩余的课程按3-3-9的配额设定任务量,顺应人性不死板,3天完成15课就好,剩余时间自由支配。

  3. 刻意练习,保证质量,绝对不要骗自己,所有示例代码,自己看完示范后,按其思路改写一遍(绝对不能照抄!那是打字员的工作,不是程序员!必须完全更改,只保留思路)

  4. 更改个人自我基本假设,未来不再是自己的人比自己的事重要,而是反过来,要将自己的事看的比自己的人重要。(感谢李善友教授讲了王东岳老师的生平故事,更感谢自己能把业余时间用在听课而不是玩游戏刷肥皂剧上)

第117集:自定义泛型深入1、子类、属性类型、重写方法类型、泛型擦除

  1. 擦除

    1. 要么同时擦除,要么子类是泛型类,同时让子类泛型字母数都要大于等于父类(子类声明时指定具体类型的情况除外)

    2. 不可子类擦除,父类泛型。

    3. 被擦除后,原泛型字母指代的类型一律视为Object

  2. 属性类型(关键看属性属于父类还是子类)

    1. 父类的属性,随父类定

    2. 子类的属性,随子类定

  3. 方法重写:随父类定

    package com.fangxing;
    
    
    //父类为泛型类
    public abstract class Father<T1,T2>{
        T1 name;
        public void test(T1 a){};
    }
    
    //子类声明时指定具体类型,另外原来的T name此时已经变为 String name
    class Child extends Father<String,Integer>{
        int size;
        public void test(String a){
        }
    }
    
    //子类是泛型类,父类也是,另外,子类泛型字母个数等于父类
    class Child2<T1,T2> extends Father<T1,T2> {
        int size; 
        public void test(T1 a){
            
        }
    }
    
    //泛型的字母顺序调换没有关系
    class Child8<T2,T1> extends Father<T1,T2> {
        int size;
        public void test(T1 a){
            
        }
    }
    
    
    //子类是泛型类,父类也是,另外,子类泛型字母个数大于父类
    class Child3<T1,T2,T3> extends Father<T1,T2>{
        T3 size; //这个T3 size属性属于子类,属性类型随子类定
        public void test(T1 a){//这个方法重写,这个T1属性随父类而定
            this.name = a;//这个T1 name属性属于父类,属性类型随父类定
        }
    }
    
    //子类是泛型类,父类不指定类型(即父类进行了擦除),原来泛型字母指代的类型一律视为Object(即原来那父类那个T name 现在变成了 Object name)
    class Child4<T1,T2> extends Father{ 
        int size;
        public void test(Object a){
            
        }
    }
    
    //子类与父类均擦除,原来泛型字母指代的类型一律视为Object
    class Child5 extends Father{
        int size;
        public void test(Object a){
            
        }
    }
    
    //这里有错误,不能让子类泛型字母数量小于父类。
    
    //class Child6 extends Father<T1,T2>{
    //    int size;
    //    public void test(T1 a){
    //        
    //    }
    //}
    
    
    //这里有错误,不能让子类泛型字母数量小于父类。
    //class Child7<T1> extends Father<T1,T2>{
    //    int size;
    //    public void test(Object a){
    //        
    //    }
    //} 
    
    
  4. 接口的泛型使用规则与类的继承一样

    package com.fangxing;
    
    public interface Comparable<T> {
        public void test(T a);
    }
    
    class Comp implements Comparable<String>{
        public void test(String a){}
    }
    
    class Comp1<T> implements Comparable<T>{
        public void test(T a){}
    }
    
    class Comp2<T> implements Comparable{
        public void test(Object a){}
    }
    
    class Comp3 implements Comparable{
        public void test(Object a){}
    }
    
    // 错误
    //class Comp4 implements Comparable<T>{
    //    public void test(Object a){}
    //}
  1. 擦除时默认设置其泛型字母代表的类型为Object,

    package com.fangxing;
    
    public class Test<T> {
        int size;
        public void test(T a){
            
        }
        
        public static void kkk1(Test<Object> a){
            
        }
        
        public static void kkk2(Test<?> a){
            
        }
        
        public static void kkk3(Test<Integer> a){
            
        }
        
        public static void main(String[] args){
            Test test1 = new Test();
            //擦除不会在编译时进行类型检查(虽然相当于Object,但其实与Test<Object>的Object也不完全等同)
            //将其泛型类型设置Object,可消除警告
    
            Test<Object> test2 = new Test<Object>();
            
            kkk1(test1);
            kkk2(test1);
            kkk3(test1);
            
            kkk1(test2);
            kkk2(test2);
            //kkk3(test2);//报错,因为没有装入Object类型    
        }
    }
    

第118集:自定义泛型深入2、无多态、通配符、无泛型数组、jdk7泛型使用

多态的两种形式:

  1. 形参使用多态

  2. 返回类型使用多态

        package test118;
    
    /**
     * @author wangtao
     * 多态的两种形式
     */
    public class Father {
        int a;
        
        //形参使用多态
        public void test(Father b){
            
        }
        
        //返回类型使用多态
        public Father test2(){
            return new Child();
        }    
    }
    
    class Child extends Father{
    
        public static void main(String[] args){
            Child k = new Child();
            
            //形参发生多态
            k.test(k);
            
            //返回值发生多态
            k.test2();
        }
    }

泛型没有多态

package test118;

public class GenericityClass<T> {
    T test;
    
    //测试泛型返回值是否能使用多态
    public GenericityClass<Father> test01(){
        //return new GenericityClass<Child>();//报错,泛型返回值不能发生多态
        //return (GenericityClass<Father>)(new GenericityClass<Child>());//报错,强转也没有用
        return new GenericityClass<Father>();//正确姿势
    }
    
    //测试泛型形参是否能使用多态
    public void test02(GenericityClass<Father> a){
        
    }
    
    public static void main(String[] args){
        //GenericityClass<Father> a = new GenericityClass<Child>();//报错 泛型不发生多态
        GenericityClass<Father> a = new GenericityClass<Father>();
        //a.test02(new GenericityClass<Child>());//报错,泛型形参不能发生多态
        a.test02(new GenericityClass<Father>());//正确姿势
        
    }

}

通配符?

  1. 通配符:? extends super【用于实现类似多态的效果】

    1. ? extends 泛型上限 <=

    2. ? super 泛型下限 >=

  2. 通配符可以用在声明类型及声明方法参数上,不能用在声明类上。

  3. ?可以接受泛型的任意类型,只能接收和输出,不能修改。

  4. ?类型不定,使用时确定类型。

    package test118;

//public class Animal<?>{ //报错,通配符?不可用于声明类
//    
//}

public class Animal<T> {
    T age;
    
    public static void test0(Animal<String> a){
        
    }
    
    public static void test1(Animal<?> a){
        
    }
    
    public static void test2(Animal<? extends Father> a){
        
    }
    
    public static void test3(Animal<? super Father> a){
        
    }
    
    public static void test4(Animal<Father> a){
        
    }
    
    public static void main(String[] args){
        //通配符?可以接收任意类型,但是通配符只能用于声明方法参数和类型,不能用于声明类。
        Animal<?> dog = new Animal<Integer>();
        
        //Animal<?> lion = new Animal<?>();//报错,不可以实例化一个泛型为通配符?的对象
        
        //给方法传参时,编译器的类型检查,是以声明时为准,而不是使用时,所以同样是String,一个可编译通过,一个不可以。
        Animal<?> mouse = new Animal<String>();
        Animal<String> cat = new Animal<String>();
        test0(cat);
        //test0(mouse); //报错 声明时的泛型字母为通配符?,与方法test0的形参不一样
        
        //
        test1(dog);
        test1(mouse);
        test1(cat);
        
        //
        Animal<Child> person1 = new Animal<Child>();
        Animal<Father> person2 = new Animal<Father>();
        Animal<?> python1 = new Animal<Child>();
        Animal<?> python2 = new Animal<Father>();

        //以下报错原因:声明时的泛型类型不适配    
        //test2(dog); //报错 
        //test2(mouse); //报错
        //test2(cat); //报错    
        //test2(python1); //报错
        //test2(python2); //报错 
                
        test2(person1); //正确 <= Father
        test2(person2); //正确 <= Father
        
        //
        //test3(person1); //报错,child<= Father
        test3(person2); //正确 >= Father
        test3(new Animal<Object>());//正确 >= Father
        
        //
        //test4(new Animal<Child>());//报错,泛型不发生多态
        
    }
    
    
    
}

    

泛型的嵌套

  1. 声明:嵌套使用泛型

    A<B<C>> a = new A<B<C>>();
  2. 使用:从外到内,层层拆分
    稍微复杂一些,但与调用没有任何关系,只是确定了类型而已。

    package test118;
    
    public class Test01<T> {
        T name;
    
        public static void main(String[] args){
            Test01<GenericityClass<String>> a = new Test01<GenericityClass<String>>();//在这一步,a.name的值还为null,未指向任何对象。
            a.name = new GenericityClass<String>();//若不让a.name指向一个GenericityClass对象,后续输出将报空指针异常的错误。
            GenericityClass<String> b = a.name;//a.name的类型与b相同
            System.out.println(b.test);    
        }
    }
    

泛型与数组

  1. 没有什么泛型数组。

package test118;

public class Test02 {
    Animal<String>[] lions;//可以声明泛型数组,但是无法创建泛型数组,没啥意义
    
    public static void main(String[] args){
        Animal[] dogs = new Animal[10];
        //Animal<String>[] cat = new Animal<String>[10];//报错,可以声明泛型数组,但无法创建泛型数组,没啥意义
        Animal<?>[] mouse = new Animal[10];//这样可行,但是依然无法控制传入数组的数据的类型。
        
        //如何确保传入数组的类型按我们的要求来?
        //思路是先将数据传入一个类,再用该类get方法return出来,return出来的同时进行强制转换(此时用泛型)
    
        MyArrayList<Integer> kk = new MyArrayList<Integer>();
        kk.add(0, 1);
        kk.add(1, 2);
        System.out.println(kk.get(0));//设定泛型为Integer类型,取出来就是Integer类型。
        System.out.println(kk.getAll());
        
    }
}

class MyArrayList<E>{
    //E[] cap = new E[10];//报错,没有什么泛型数组
    private Object[] cap = new Object[10];
    
    public void add(int index,E e){
        cap[index] = e;
    }
    
    public E[] getAll(){
        return (E[]) cap;
    }
    
    public E get(int index){
        return (E)cap[index];
    }
}

JDK1.7的一个新增特性

package test118;

import java.util.HashSet;
import java.util.Set;

public class Test03 {
    public static void main(String[] args){
        Set<String> aa = new HashSet<String>();
        Set<String> bb = new HashSet<>();//JDK1.7后,第二次使用同样的泛型可以少打几个字母了~~~
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值