造轮子的时候不敢用不会用泛型?那你看这篇就够了!

阅读本文解决什么问题?

解决许多java开发 或者android开发 在平时写一些基础架构,或者是造一些轮子的时候不敢用泛型,用很差泛型的问题。 甚至有些人使用泛型的时候报错都只会用idea提示的方法来修改代码,殊不知这样改的缘由,也不知道强转泛型会有什么恶果。java

泛型用来解决什么问题

先定义一个模仿List 的泛型list。 咱们来看看这个乞丐版的list能帮咱们作什么事android

public class CustomList<T> {
    Object[] array = new Object[0];

    public T get(int index) {
        return (T) array[index];
    }

    public void add(T instance) {
        array[array.length - 1] = instance;
    }
}
复制代码

看看怎么使用他bash

CustomList<String> customList = new CustomList<>();
        customList.add("hahahaha");
        String c = customList.get(0);
复制代码

到这,咱们来看看 到底有啥好处。 首先看这个add方法,有了泛型之后,咱们就不须要担忧类型转换错误了。 由于咱们在定义的时候 指定了泛型的类型,因此若是咱们在调用add方法的时候传了一个 非string类型的 那么ide就会报错了,即便你不用ide 用记事本写,你编译起来也会报错的。 这就是静态语言的好处了, 不少bug 在编译的时候告诉你 不用像js 那么蛋疼。markdown

而后再看看get 这个函数,想一下 若是没有泛型的话, 咱们get出来的值 是必定要强转成string才能赋值给c的, 可是如今有了泛型, 因此你能够直接get出来,这个类型转换的东西 早就帮你作好了。架构

总结一下泛型的好处:app

  1. 避免运行时出错,编译时就告诉你
  2. 方便你使用,省略强制类型转换的代码

泛型为何不能够是静态的?

这边能够想一下,为何泛型不能用静态的去定义?你怎么改都是没法突破这个规则,是没法编译成功的。ide

前面的例子咱们能够知道,泛型主要用来能够初始化每一个实例的。 注意是每一个实例,他是动态肯定的,函数

取决于你当时使用的时候 传的是什么参数,好比List<Object> List<String> List<Teacher>ui

对于一个静态变量来讲 你若是用泛型 那就会乱套了。 例如咱们上面截图的例子你用泛型会发生什么?idea

static Object ins? static String ins? static Teacher ins? 你们都叫ins,那我怎么知道 这个ins

到底应该是哪一个类型的? 静态变量 全局惟一啊。 因此泛型是绝对不能用static来修饰的

这个地方必定要想明白了,想明白了,对你理解泛型是有好处的。

泛型的一种错误写法

这种就是一种典型的错误写法,明明接口中有泛型的,结果实体类中 把这个泛型给抹掉了。

虽然能够编译经过,可是这种写法就毫无心义了。

这种才是正确的写法,和前面那种错误的写法相比 咱们明显能够省略一次强制类型转换。

你们能够比对一下这2种写法 和 文章开头泛型的2个优势。仔细体会一下。

如何正确extends泛型

泛型限制

interface IShop<T> {
    T buy(float price);
}


interface IPhoneShop2<T> extends IShop<T> {
    void repair(T phone);
}
复制代码

前面咱们说道 ,泛型最大的好处就是方便使用,好比上面的代码 咱们使用起来就很轻松如意,可是由于这样的写法 太随意 因此要加一层限制。 上面的代码中,咱们明明是一个手机商店,但实际使用的时候 却能够随便传, 传String 传Apple 传啥都行。 这和设计者的本意是不一致的。

因此泛型还能够加限制

interface Phone {

}

interface IPhoneShop2<T extends Phone> extends IShop<T> {
    void repair(T phone);
}

复制代码

这样一来就能够限制咱们使用时的类型,限制他必定得是Phone的类型才行。 考虑到java 是支持多接口,可是不支持多继承的,泛型的限制也遵循这个规定。

泛型限制在list中的迷惑性

来说讲泛型中一个令不少人想不通的地方

定义一个水果 而后有苹果和香蕉

interface TFruit {

}

class Apple2 implements TFruit {
}

class Banana2 implements TFruit {
}
复制代码

而后咱们看看他们的使用

报红的地方为何报错 是不少人想不明白的地方吗,咱们的apple 命名是fruit的子类啊,为啥报错?

换个角度来思考一下这个问题:

因此对于 list 的 泛型来讲, 他的类型 是动态肯定的, 是没办法在编译期 肯定的, 因此你须要保证他 在= 两边 泛型都是绝对一致的 才能声明成功,不然一定失败

继续看:

这个例子其实不难理解 为何add 方法不能编译经过。

看到这,我相信不少人 都想告辞了。。。这tmd 泛型限制真多,咋用?不用了,之后本身造轮子自动屏蔽泛型了。

不要紧 耐心一下,咱们再缕一遍。

// =左边: 表明 我想要一个水果  =右边 :我给你个苹果  逻辑没问题 编译经过
        TFruit fruit = new Apple2();
        // =左边: 表明 我想要一个水果的list 任意的水果 =右边 :我给你个任意水果的list 逻辑没问题 编译经过
        List<TFruit> tf1 = new ArrayList<TFruit>();
        //既然是个水果的list 那我 add 苹果香蕉 确定没问题
        tf1.add(new Apple2());
        tf1.add(new Banana2());


        // =左边: 表明 我想要一个水果的list 任意的水果  =右边 :我给你一个苹果的list
        //这样编译确定不经过,由于我想要的是水果的list 你却给我一个苹果的list 这样你让我就没办法玩了
        // 我想要水果 你只给我苹果 那香蕉 葡萄 西瓜 我就没办法要了,因此你确定不行 编译不过
        List<TFruit> tf2 = new ArrayList<Apple2>();



        //=左边: 表明 我想要一个list,这个list 必须是一个水果的类型,且只能是一种水果的类型   =右边 :我给你一个苹果的list
        //符合要求 编译经过
        List<? extends TFruit> tf3 = new ArrayList<Apple2>();
        //我这个tf3 要求的是必须是一种水果的类型,可是我并不知道是那种类型,多是水果 多是葡萄 多是香蕉
        // 因此你直接往我这塞一个肯定好的水果  我确定是不接受的,编译确定失败
        tf3.add(new Apple2());
        tf3.add(new Banana2());
复制代码

?extends 好像有点蠢?

前面的文章看完,是否是以为 这个?extends 有点蠢了,实际上 他在某种场景下 是 十分有用的(废话 否则java为啥要这么设计)

仍是上面的水果,咱们增长一个方法 返回对应水果的价格

interface TFruit {
    int getPrice();
}

class Apple2 implements TFruit {
    @Override
    public int getPrice() {
        return 1;
    }
}

class Banana2 implements TFruit {
    @Override
    public int getPrice() {
        return 2;
    }
}
复制代码

看看会有什么问题

看这个函数的参数, 这个函数的参数 意思是 我想要一个list ,这个list里面 能够听任何水果, 只要是水果就行,

可是在调用的时候 咱们给他的 倒是苹果的list 和 香蕉的list ,这就不是他想要的了,我想要任意类型的水果 你却给我 苹果或者是香蕉的,你帮我指定了具体类型 那确定是不能够的。

因此这个时候 ? extends 就出场了

改完之后 就直接编译成功了:

回想一下上一小节的内容,这个? extends 不就是表明 想要任意一种水果吗

你既然想要的是任意 一种水果,那我给你苹果或者香蕉 确定是ok的。

大家使用的泛型埋坑了吗?

并且是运行期间报错了。后果比较严重,不易察觉。

一个香蕉固然不能转成苹果。

平时写代码的时候必定不要这么写。

?super 又是啥,怎么用。

改为

就能够, 这里怎么理解?

加上? super就表明 等号右边的东西 你只要能够接受一个苹果的list就能够了。

相关文章
相关标签/搜索