自定义泛型JAVA_116-118

来源:http://www.bjsxt.com/
1、S02E116_01116_自定义泛型泛型类泛型接口_泛型方法
(1)发生多态时,强制类型转换和手动类型检查(避免转换错误java.lang.ClassCastException):
Object obj = 80;
int score = (int)obj;//jdk1.7以后Object–>>Integer–>>自动拆箱
//int score = (Integer)obj;//jdk1.6之前
Student stu = new Student(80,90);//形参都是Object类型,存入整数时,int–>>Integer–>>Object
(2)泛型:
——【1】泛型就是参数化类型,使用广泛的类型;
——【2】起因:数据类型不明确
————(a)装入数据的类型都被当作Object对待,从而“丢失”自己的实际类型;
————(b)获取数据时往往需要转型,效率低,容易产生错误;
——【3】作用:
————(a)安全:在编译时检查类型安全;
————(b)省心:所有的强制转换都是自动和隐式的,提高代码的重用率;
(3)泛型类:定义类时使用泛型
——【1】格式:<>

class 类名<字母列表>{
        修饰符 字母 属性;
        修饰符 构造器(字母){}
        修饰符 返回类型 方法(字母){}
}

泛型常见字母:T(Type表示类型),K V(分别代表键值中的Key Value),E(代表Element),?表示不确定的类型。
泛型类声明时的字母不能使用在静态属性、静态方法上(static不能访问泛型类的类型参数)
——【2】使用:指定具体类型
————(a)编译时会进行类型检查
————(b)获取数据时不需要强制类型转换
泛型类使用时不能指定基本类型,只能是引用类型

(4)泛型接口:字母不能使用在静态属性上,更不能用在全局常量上,只能使用在方法中
(5)泛型方法:
——【1】修饰符 <字母> 返回类型 方法名(字母){}
<字母>在返回类型前面,修饰符可以有static
——【2】注意:泛型还可以定义在方法中,是否拥有泛型方法,与其所在的类是否泛型没有关系
——【3】只能访问相应的对象的信息(get、print…),不能修改信息(还不确定类型,不能set…)
2、S02E117_01自定义泛型子类属性类型重写方法类型泛型擦除
(1)子(实现)类
——【1】非泛型子类声明时指定泛型父类 | 接口的具体类型
——【2】泛型父类 | 接口的子类为泛型类
——【3】子类为泛型类,泛型父类 | 接口不指定类型(泛型的擦除),继承的属性类型用Object替换
——【4】子类与父类 | 接口同时泛型擦除
——【5】错误:子类擦除,父类 | 接口使用泛型
擦除统一使用Object对待

package com.test.generic;
/**
 * 父类为泛型类
 * <br>1.属性
 * <br>2.方法
 * <p>要么同时擦除,要么子类大于等于父类的类型,
 * 不能子类擦除,父类泛型
 * <br>1.属性类型
 * <br>父类中,随父类而定
 * <br>子类中,随子类而定
 * <br>2.方法重写
 * <br>随父类而定
 */
public abstract class Father<T,T1> {
    T name;
    public abstract void test(T t);
}
/**
 * 非泛型子类声明时指定泛型父类的具体类型
 * <br>属性类型为具体类型
 * <br>方法同理
 */
class Child1 extends Father<String,Integer>{
    int t2;
    @Override
    public void test(String t) {
        name = "指定的具体类型String";
    }
}
/**
 * 泛型父类的子类为泛型类
 * <br>类型数不少于泛型父类的,类型顺序可以不同
 * <br>类型在使用时确定
 */
class Child2<T1,T,T2> extends Father<T,T1>{
    int t2;
    @Override
    public void test(T t) {

    }
}
/**
 * 子类为泛型类,泛型父类不指定类型(泛型的擦除),继承的属性类型用Object替换
 */
class Child3<T1,T2> extends Father{
    T1 t2;
    @Override
    public void test(Object t) {//T用Object替换
        this.name = "name类型为Object";
    }
}
/**
 * 子类与父类同时泛型擦除
 */
class Child4 extends Father{
    int t2;
    @Override
    public void test(Object t) {//T用Object替换
        this.name = "name类型为Object";
    }
}
/**
 * 错误:子类擦除,父类使用泛型
 */
/*
class Child5 extends Father<T, T1>{
    int t2;
    @Override
    public void test(T t) {

    }
}
*/

(2)泛形擦除
——【1】擦除:
————(a)在使用时没有指定具体的类型
————(b)子类继承时没有指定类型
——【2】处理:
————(a)擦除后不类型检查
————(b)一旦擦除之后按Object接收
————(c)使用时没有指定具体的类型,存在编译警告,加上可以去除,但是会类型检查(声明时的泛型跟使用时的泛型不同会报错)

package com.test.generic;

public class Student<T>{

    private T javaScore;
    public void setJavaScore(T t){
        this.javaScore = t;
    }

    public static void main(String[] args){
        Student<Object> stu = new Student<Object>();//消除警告使用<Object>,但是...
        stu.setJavaScore("ab");//以Object对待
        //test(stu);//类型检查,报错。要的是Integer,传的是Object
        test1(stu);//不报错,声明时类型不确定

        Student stu1 = new Student();//使用时没有指定具体的类型,警告
        test(stu1);//不报错,擦除后不类型检查,警告
        test1(stu1);//不报错,声明时类型不确定

        stu1.setJavaScore("参数为Object类型");//警告
        System.out.println(stu1.javaScore);
    }

    public static void test(Student<Integer> a){
        a.setJavaScore(123);
        System.out.println(a.javaScore);
    }
    public static void test1(Student<?> a){//?类型不确定
    }
}

3、S02E118_01自定义泛型无多态通配符_无泛型数组_jdk7泛型使用
(1)泛型没有多态
——【1】回顾:类与接口存在多态

package com.test.generic;

/**
 * 多态的两种形式
 */
public class Fruit {

    public static void main(String[] args) {
        Fruit f = new Apple();
        test(new Apple());
    }
    //形参使用多态
    public static void test(Fruit f){

    }
    //返回类型使用多态
    public static Fruit test2(){
        return new Apple();
    }
}
class Apple extends Fruit{

}

——【2】泛型没有多态
————(a)直接使用:A a = new A();错误
————(b)方法形参与返回类型也不存在泛型多态
——【3】不能使用instanceof判断是否为泛型实例(a instanceof A)
(2)通配符:? extends super
——【1】可以用在声明类型及声明方法参数上,不能用在声明类上
——【2】?可以接受泛型的任意类型,只能接收和输出,不能修改(方法声明时参数无法正确知道具体的类型,因此不能修改)
——【3】? extends 泛型上限 <=
——【4】? super 泛型下限 >=

package com.test.generic;
/**
 * 通配符
 * ?:类型不定,使用时确定类型
 * <br>使用:声明类型|声明方法上,不能声明类|使用时
 * <br>? extends:<= 上限  指定类型:子类|自身
 * <br>? super:      >= 下限  指定类型:父类|自身
 */
public class Consumer<T> {
    T number;

    public static void main(String[] args) {
        Consumer<?> con = new Consumer<String>();//?使用在声明类型,使用时确定类型String
        test(new Consumer<Integer>());

        test2(new Consumer<Apple>());//指定类型为子类(Apple)或自身(Fruit)
        //test3(new Consumer<Apple>());//泛型没有多态

        //test4(new Consumer<Apple>());//指定类型为父类或自身(Fruit)
        test4(new Consumer<Object>());
        test4(new Consumer<Fruit>());

        //test4(con);//使用时要确定类型,Consumer<?> con类型不定
        con = new Consumer<Fruit>();
        //test4(con);//编译时看左边,Consumer<?> con类型不定
    }
    public static void test(Consumer<?> con){}
    public static void test2(Consumer<? extends Fruit> con){}//<=
    public static void test3(Consumer<Fruit> con){}
    public static void test4(Consumer<? super Fruit> con){}//>=
}

(3)泛型嵌套
——【1】声明:嵌套使用泛型
A

package com.test.generic;

public class Boss<T> {
    T con;

    public static void main(String[] args) {
        //泛型的嵌套
        Boss<Consumer<String>> boss = new Boss<Consumer<String>>();
        //从外到内拆分
        boss.con = new Consumer<String>();
        Consumer<String> con = boss.con;
        String num = con.number;
        System.out.println(num);
    }
}

(4)泛型与数组
——【1】没有泛型数组,不能创建泛型数组
——【2】可以只有声明,可以使用?
A[] a1 = null;//没有意义
A

package com.test.generic;
/**
 * 没有泛型数组
 * 声明可以使用,但是创建失败。
 */
public class Array {

    public static void main(String[] args) {
        Student<?>[] arr = new Student[10];//声明可以,但是没有意义

        MyArrayList<String> strList = new MyArrayList<String>();
        strList.add(0, "a");
        System.out.println(strList.getElem(0));
    }
}
/**
 * 变相使用泛型
 */
class MyArrayList<E>{
    //E[] cap = new E[10];//没有泛型数组,类型不定,开辟不了空间
    Object[] cap = new Object[10];

    public void add(int idx,E e){
        cap[idx] = e;
    }
    @SuppressWarnings("unchecked")
    public E[] getAll(){
        return (E[]) cap;
    }
    @SuppressWarnings("unchecked")
    public E getElem(int idx){
        return (E)cap[idx];
    }
}

(5)jdk7泛型的改进
JDK7改进:声明时指定泛型即可,创建对象不用再次编写类型
如:A a = new A<>();

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值