当前位置: 首页 > news >正文

Java 泛型(一) 泛型使用基础

泛型Generics

  

  所谓泛型,就是变量类型的参数化。

  泛型是JDK1.5中一个最重要的特征。通过引入泛型,我们将获得编译时类型的安全和运行时更小的抛出ClassCastException的可能。

  在JDK1.5中,你可以声明一个集合将接收/返回的对象的类型。

  使用泛型时如果不指明参数类型,即泛型类没有参数化,会提示警告,此时类型为Object。

 

为什么使用泛型

  使用泛型的典型例子,是在集合中的泛型使用。

  在使用泛型前,存入集合中的元素可以是任何类型的,当从集合中取出时,所有的元素都是Object类型,需要进行向下的强制类型转换,转换到特定的类型

  比如:

List myIntList = new LinkedList(); // 1

myIntList.add(new Integer(0)); // 2

Integer x = (Integer) myIntList.iterator().next(); // 3   

  第三行的这个强制类型转换可能会引起运行时的错误。

  泛型的思想就是由程序员指定类型,这样集合就只能容纳该类型的元素。

  使用泛型:

List<Integer> myIntList = new LinkedList<Integer>(); // 1'

myIntList.add(new Integer(0)); // 2'

Integer x = myIntList.iterator().next(); // 3'

  将第三行的强制类型转换变为了第一行的List类型说明,编译器会为我们检查类型的正确性。这样,代码的可读性和健壮性也会增强。

 

泛型使用基础

  例如:

public interface List <E> 
{
    void add(E x);
    Iterator<E> iterator();
}

public interface Iterator<E> 
{
    E next();
    boolean hasNext();
}

 

  尖括号中包含的是形式类型参数formal type parameters),它们就如同一般的类型一样,可以在整个类的声明中被使用。

  当类被使用时,会使用具体的实际类型参数actual type argument)代替。

  比如前面的例子中的List<Integer>,那么所有的E将会被Integer类型所代替。

  泛型类型参数只能被类或接口类型赋值,不能被原生数据类型赋值,原生数据类型需要使用对应的包装类。

  形式类型参数的命名:尽量使用单个的大写字母(有时候多个泛型类型时会加上数字,比如T1,T2),比如许多容器集合使用E,代表element(元素),Map中用K代表键keys,V代表值。

 

 

泛型容器的实现讨论

  不能用new的形式来创建一个泛型数组。 

  如下:

public class SimpleCollection<T>
{
   private T[] objArr;
   private int index = 0;

   public SimpleCollection()
   {
      //Error: Cannot create a generic array of T
      objArr = new T[10];   
   }
}

  会报错。

 

  如何创建一个数组让它接受所有可能的类型呢?

public class SimpleCollection<T>
{
    private T[] objArr;
    
    private int index = 0;
    public SimpleCollection()
    {
        //Error: Cannot create a generic array of T
        //objArr = new T[10];
        
        //Warning: Unchecked cast from Object[] to T[]
        objArr = (T[]) new Object[10];
        
    }

}

 

  这个形式虽然可以做到,但是会产生一个警告

  查看ArrayList中的实现,可以发现它是使用了一个Object类型的数组:

private transient Object[] elementData;

 

  在取出的时候(get方法中)使用了类型转换:

(E) elementData[index];

 

 

泛型和子类

List<String> ls = new ArrayList<String>(); // 1

List<Object> lo = ls; // 2

 

  一个String类型的List是一个Object类的List吗?

  不可以,Java编译器将会在第二行产生一个编译错误,因为它们的类型不匹配。

  这样就避免了如果lo引入加入Object类型的对象,而ls引用试图将其转换为String类型而引发错误。所以编译器阻止了这种可能。

 

继承泛型类别

  直接用例子说明:

  父类:

public class Parent<T1,T2>
{
    private T1 foo1;
    private T2 foo2;
    
    public T1 getFoo1()
    {
        return foo1;
    }
    public void setFoo1(T1 foo1)
    {
        this.foo1 = foo1;
    }
    public T2 getFoo2()
    {
        return foo2;
    }
    public void setFoo2(T2 foo2)
    {
        this.foo2 = foo2;
    }    

}

 

  子类继承父类:

public class Child<T1, T2, T3> extends Parent<T1, T2>
{
    private T3 foo3;

    public T3 getFoo3()
    {
        return foo3;
    }

    public void setFoo3(T3 foo3)
    {
        this.foo3 = foo3;
    }
    
}

 


实现泛型接口

  见例子:

  泛型接口:

public interface ParentInterface<T1,T2>
{
    public void setFoo1(T1 foo1);
    public void setFoo2(T2 foo2);
    public T1 getFoo1();
    public T2 getFoo2();

}

  子类实现泛型接口:

public class ChildClass<T1,T2> implements ParentInterface<T1, T2>
{
    private T1 foo1;
    private T2 foo2;
    
    @Override
    public void setFoo1(T1 foo1)
    {
        this.foo1 = foo1;
        
    }
    @Override
    public void setFoo2(T2 foo2)
    {
        this.foo2 = foo2;
    }
    @Override
    public T1 getFoo1()
    {
        return this.foo1;
    }
    @Override
    public T2 getFoo2()
    {
        return this.foo2;
    }

}

 

参考资料:

  圣思园张龙老师Java SE视频教程。

  The Java Tutorials : Lesson: Generics (Updated)

  http://docs.oracle.com/javase/tutorial/java/generics/index.html

  Lesson: Generics

  http://docs.oracle.com/javase/tutorial/extra/generics/index.html

 

转载于:https://www.cnblogs.com/mengdd/archive/2013/01/21/2869778.html

相关文章:

  • Codeforces 264B Good Sequences ★ (分解素因子+DP)
  • Unity(五):使用场景Ⅱ:用于单例模式
  • 【ZZ】9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的2012求职之路...
  • 密码绑定至密码文本框中
  • 使用PowerDesigner建立数据库模型
  • outerHTML兼容方法(jquery)
  • 解决compilation debug=true targetFramework=4.0 问题
  • Python学习笔记《Python核心编程》第13章 面向对象编程
  • GDI+ 图片高亮处理
  • int 反射到未知的 Enum , 使用 Enum.ToObject
  • USACO 3.1.1 Agri-Net
  • 关于SharePoint 2010 SP1
  • IE6,7下LI浮动不能自动换行,最后一行被隐藏掉解决办法
  • win7 64位注册表操作兼容问题解决(vc6)
  • 没有安装或未能初始化关联的源代码管理插件
  • js中forEach回调同异步问题
  • js中的正则表达式入门
  • Leetcode 27 Remove Element
  • React系列之 Redux 架构模式
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • Spark RDD学习: aggregate函数
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • vue总结
  • 从 Android Sample ApiDemos 中学习 android.animation API 的用法
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 看域名解析域名安全对SEO的影响
  • 容器服务kubernetes弹性伸缩高级用法
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 微信开源mars源码分析1—上层samples分析
  • 因为阿里,他们成了“杭漂”
  • ​Spring Boot 分片上传文件
  • #pragma multi_compile #pragma shader_feature
  • (2)Java 简介
  • (C#)if (this == null)?你在逗我,this 怎么可能为 null!用 IL 编译和反编译看穿一切
  • (分布式缓存)Redis持久化
  • (附源码)ssm高校志愿者服务系统 毕业设计 011648
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (算法)Game
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • .NET企业级应用架构设计系列之结尾篇
  • .NET企业级应用架构设计系列之应用服务器
  • .NET文档生成工具ADB使用图文教程
  • .NET与 java通用的3DES加密解密方法
  • .NET中 MVC 工厂模式浅析
  • .so文件(linux系统)
  • @ModelAttribute注解使用
  • @RequestMapping处理请求异常
  • [ vulhub漏洞复现篇 ] Django SQL注入漏洞复现 CVE-2021-35042
  • [ 蓝桥杯Web真题 ]-Markdown 文档解析
  • [ 云计算 | AWS ] AI 编程助手新势力 Amazon CodeWhisperer:优势功能及实用技巧
  • [2016.7 test.5] T1
  • [C/C++]关于C++11中的std::move和std::forward
  • [C++数据结构](22)哈希表与unordered_set,unordered_map实现