Java泛型拾遗

先上百度百科的解释

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。

好吧,我知道这如果初次解除泛型直接就懵掉了,这都是些什么???
理解泛型第一步理解类型信息擦除。

1.简单泛型
类型信息擦除,举两个例子

@Test
public void testGeneric() {
    List<String> list1 = new ArrayList<String>();
    List<Integer> list2 = new ArrayList<Integer>();
    System.out.println("list1类型" + list1.getClass());
    System.out.println("list2类型" + list2.getClass());
}

list1类型class java.util.ArrayList
list2类型class java.util.ArrayList

@Test
public void testGeneric1() {
    List list = new ArrayList();
    list.add("xyz");
    list.add(100);
    for (int i = 0; i < list.size(); i++) {
        String name = (String) list.get(i);
        System.out.println("name:" + name);
    }
}

name:xyz
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

这个例子很明显编译阶段没问题,执行阶段挂掉了。
关于这个举个不恰当的例子:鱼和猫不能放到一个篮子里, 放进去没事, 拿出来还想拿到鱼的话,那就是太单纯了。
所以当时就要避免这情况发生,如果篮子里有个猫,就不放往里放鱼,如果有鱼也就让猫远点,这是不是解释了泛型。

具体的看下List接口的定义就了解了。

2.泛型接口

这个就拿上面List接口为例

public interface List<E> extends Collection<E> {...}

public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{...}

这样的泛型接口很合适于工厂模式,这个留个坑在这,设计模式我已经放那了,我希望能写完那个系列...(拖延症患者伤不起, 设计模式我绝对写完,给自己点信心,总要有点坚持)

3.泛型方法
      先对泛型方法做一个声明,拥有泛型方法的类可以是泛型类,也可以不是泛型类,其实就是跟类没啥关系喽
就是那句流行的话,你强任你强...

public class GenericTest {
    public <T> void printClassInfo(T t) {
        System.out.println(t.getClass().getName());
    }
}

@Test
public void testGeneric2() {
    GenericTest genericTest = new GenericTest();
    genericTest.printClassInfo("String");
    genericTest.printClassInfo(new Integer("123"));
    genericTest.printClassInfo(genericTest);
}

java.lang.String
java.lang.Integer
com.test.GenericTest

这样一个类既可以传入String Integer 还有自定义的类型 好神奇的方法重载有没有

4.泛型类

public class GenericClass<T> {
    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }

    private T obj;
}

@Test
public void testGeneric3() {
    GenericClass genericClassTest = new GenericClass();
    genericTest.printClassInfo("String");
    genericTest.printClassInfo(new Integer("123"));
    genericTest.printClassInfo(genericTest);
}

testGeneric

泛型边界
     可以用无界泛型调用的方法, 就是可以用Object调用的方法
不限制边界,那就是Object

Java泛型编程中使用extends关键字指定泛型参数类型的上边界(后面还会讲到使用super关键字指定泛型的下边界),即泛型只能适用于extends关键字后面类或接口的子类。
Java泛型编程的边界可以是多个,使用如<T extends A & B & C>语法来声明,其中只能有一个是类,并且只能是extends后面的第一个为类,其他的均只能为接口(和类/接口中的extends意义不同)。
使用了泛型边界之后,泛型对象就可以使用边界对象中公共的成员变量和方法。

@Test
public void testGeneric4() {
    GenerateAnimal dog = new GenerateAnimal(new Dog());
    dog.getName();
}

public class Dog implements Animal {
    @Override
    public String getName() {
        System.out.println("dog");
        return "dog";
    }
}

public interface Animal {
    String getName();
}

public class GenerateAnimal<T extends Animal> {
    private T t;
    GenerateAnimal(T t){
        this.t = t;
    }

    public String getName() {
        return t.getName();
    }
}

泛型通配符

@Test
public void testGeneric5() {
    Fruit<String> f1 = new Fruit<>("平凡如我");
    Fruit<Integer> f2 = new Fruit<>(77);
    Fruit<Double> f3 = new Fruit<>(22.1);
    getData(f1);
    getData(f2);
    getData(f3);

    // getFruitData(f1); 编译问题
    getFruitData(f2);
    getFruitData(f3);
}

private void getData(Fruit<?> f) {
    System.out.println("Fruit :"  + f.getData());
}

private void getFruitData(Fruit<? extends Number> f) {
    System.out.println("Fruit :"  + f.getData());
}

Fruit :平凡如我
Fruit :77
Fruit :22.1
Fruit :77
Fruit :22.1

@Test
public void testGeneric6() {
    Fruit<String> f1 = new Fruit<>("平凡如我");
    Fruit<Integer> f2 = new Fruit<>(77);
    Fruit<Double> f3 = new Fruit<>(22.1);
    //getFruitSupperData(f1); // 编译问题
    //getFruitSupperData(f3); // 编译问题
    getFruitSupperData(f2);

}

private void getFruitSupperData(Fruit<? super Integer> f) {
    System.out.println("Fruit :"  + f.getData());
}

总结

关于泛型这些也差不多了,在我理解,Java是一种强类型语言,而泛型,使参数类型是可变化的,当然上面的例子与泛型的实际应用还差比较远,希望之后能更融会贯通的应用泛型。

时间: 2024-08-06 07:58:24

Java泛型拾遗的相关文章

泛型拾遗一下

一.为什么想到再学习一下泛型?    最近需要写几个这样的报表,怕领导看到我做一个隐藏哈,你们懂的~哈哈~ 然后基本的类型返回都是一样的格式就是生成一个json喽,有个什么父亲节点这种,具体那个什么节点类型的我就不说了,当然这个插件还没有改造完成,等等有时间的时候我准备在完善一下这个插件.这个当时把大神东西拷下来的时候是有点问题,我稍微修复了一下,准备等等忙完这段时间再好好扩展一下.接下来就说我们要关注的重点泛型,因为报表的类型都基本一样,所以返回的类型也基本相同,无谓就是多创建了几个实体类然后

跟王老师学泛型(九):泛型拾遗

泛型拾遗 主讲教师:王少华 QQ群:483773664 学习目标 掌握泛型方法与类型通配符的区别 泛型与方法重载 泛型与数组 一.泛型方法和类型通配符的区别 (一)大多数时候,可以使用泛型方法来替换类型通配符 比如这样一个需求:定义一个方法,接收一个任意集合,并打印出集合中的所有元素.泛型方法和类型通配符都可以实现 1 2 3 4 5 6 7 8 9 10 11 12 13 public class Need {     public <T> void printCollection(Coll

Java泛型中的PECS原则

今天在写代码的时候使用到了这样一个方法签名: public void foo(Map<String, String> map); 在写这个参数的时候正好在想一些关于泛型的东西,于是: public void foo(Map<? extends String, ? extends String> map); 这两种写法有什么区别呢?记得以前和同学讨论过这个问题,但后来没有记下来,渐渐又淡忘了.今天又去翻了好多资料,总算找到一些可以参考的,赶紧记在这里方便以后温故知新啦.好了,言归正传

Java泛型的协变

在上篇<Java泛型的基本使用>这篇文章中遗留下面问题,即将子类型也能加入到父类型的泛型中.要实现这样的功能必须借助于协变. 实验准备 如今在上篇文章展示的Decorator类型的基础上,添加一些代码,如代码清单1所看到的. 代码清单1 /** * * 描 述:Exp2使用br/> * 作 者:jiaan.gja<br/> * 历 史: (版本号) 作者 时间 凝视 <br/> * @param itemList */ public void doDecorate

2017.4.5 Java 泛型

Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数. 假定我们有这样一个需求:写一个排序方法,能够对整形数组.字符串数组甚至其他任何类型的数组进行排序,该如何实现? 答案是可以使用 Java 泛型. 使用 Java 泛型的概念,我们可以写一个泛型方法来对一个对象数组排序.然后,调用该泛型方法来对整型数组.浮点数数组.字符串数组等进行排

关于Java泛型的使用

在目前我遇到的java项目中,泛型应用的最多的就属集合了.当要从数据库取出多个对象或者说是多条记录时,往往都要使用集合,那么为什么这么使用,或者使用时有什么要注意的地方,请关注以下内容. 感谢Windstep. 原文链接:http://www.cnblogs.com/lwbqqyumidi/p/3837629.html 原文标题:Java总结篇系列:Java泛型 (我的第一篇水文,233)

java 泛型 窜讲

一.为什么使用泛型      复用性:泛型的本质就是参数化类型,因而使用编写的泛型代码可以被许多不同类型的对象所复用.      安全性:在对类型Object引用的参数操作时,往往需要进行显式的强制类型转换.这种强制类型转换需要在运行时才能被发现是否转换异常,通过引入泛型能将在运行时才能检查类型转换,提前到编译时期就能检查. 二.自定义泛型 java中自定义泛型分为三种:泛型类.泛型接口.泛型方法. 下面使用一个案例演示泛型类.泛型方法,泛型接口类似,所以不再演示. // 自定义泛型类publi

Java HashMap拾遗

Java HashMap拾遗 @author ixenos 零碎知识 尽量返回接口而非实际的类型,如返回List.Set.Map而非ArrayList.HashSet.HashMap,便于更换数据结构,而客户端代码不用改变.这就是针对抽象编程 Map.entrySet 方法返回Map映射的 Set 视图Set<Map.Entry<K,V>>,维护entry键值对 该 set 受Map映射支持,所以对Map映射的更改可在此 set 中反映出来,反之亦然! 如果对该 set 进行迭代的

1月21日 - (转)Java 泛型

java泛型 什么是泛型? 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类.可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样. 可以在集合框架(Collection framework)中看到泛型的动机.例如,Map 类允许您向一个 Map 添加任意类的对象,即使最常见的情况是在给定映射(map)中保存某个特定类型(比如 String)的对象. 因为 M