Java之泛型
1. 概述
          在引入泛型之前,Java类型分为原始类型、复杂类型,其中复杂类型分为数组和类。引入泛型后,一个复杂类型就可以在细分成更多的类型。
          例如原先的类型List,现在在细分成List<Object>, List<String>等更多的类型。
          注意,现在List<Object>, List<String>是两种不同的类型,他们之间没有继承关系,即使String继承了Object。下面的代码是非法的:
List<String> ls = new ArrayList<String>();
List<Object> lo = ls;
这样设计的原因在于,根据lo的声明,编译器允许你向lo中添加任意对象(例如Integer),但是此对象是List<String>,破坏了数据类型的完整性。
         在引入范型之前,要在类中的方法支持多个数据类型,就需要对方法进行重载,在引入范型后,可以解决此问题(多态),更进一步可以定义多个参数以及返回值之间的关系。例如:
public void write(Integer i, Integer[] ia);
public void write(Double d, Double[] da);
的范型版本为:
public <T> void write(T t, T[] ta);
在看下面代码:
 public class GenericTest {
     public static void main(String[] args) {
         List list = new ArrayList();
         list.add("qqyumidi");
         list.add("corn");
         list.add(100);
         for (int i = 0; i < list.size(); i++) {
             String name = (String) list.get(i); //
             System.out.println("name:" + name);
         }
     }
 }
定义了一个List类型的集合,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。这是完全允许的,因为此时list默认的类型为Object类型。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他编码原因,很容易出现类似于//1中的错误。因为编译阶段正常,而运行时会出现“java.lang.ClassCastException”异常。因此,导致此类错误编码过程中不易发现。
通过使用泛型,解决上面异常,修改代码如下:
 public class GenericTest {
     public static void main(String[] args) {
         /*
         List list = new ArrayList();
         list.add("qqyumidi");
         list.add("corn");
         list.add(100);
         */
         List<String> list = new ArrayList<String>();
         list.add("qqyumidi");
         list.add("corn");
         //list.add(100);   // 1  提示编译错误
         for (int i = 0; i < list.size(); i++) {
             String name = list.get(i); //
             System.out.println("name:" + name);
         }
     }
 }
总结: 使用泛型可以指代任意对象类型,定义的容器所放的内容是一个统一的类型;
java中泛型的引入主要是为了解决两个方面的问题:
    1. 集合类型元素在运行期出现类型装换异常,引入泛型增加编译时类型的检查;(即:消除强制类型转换,提高 Java 程序的类型安全)
    2. 解决开发时重复代码的编写,能够复用算法。(比如:在类中的方法支持多个数据类型,就需要对方法进行重载)
2. 定义泛型类
我们直接上代码:
 package com.learn.chap06.sec01;
 public class Fdemo<T> {  // 泛型类
     private T a;
     public Fdemo(T a) {
         super();
         this.a = a;
     }
     public T getA() {
         return a;
     }
     public void setA(T a) {
         this.a = a;
     }
     public void print(){
         System.out.println("Obeject类型为:"+a.getClass().getName());
     }
 }
package com.learn.chap06.sec01;
/**
* 定义泛型类 (使用泛型可以指代任意对象类型)
* @author Administrator
*
*/
public class Fdemotest { public static void main(String[] args) {
Fdemo<Integer> test = new Fdemo<Integer>(12);
test.print();
System.out.println("test="+test.getA()); Fdemo<String> strFdemo = new Fdemo<String>("我是中国人");
strFdemo.print();
System.out.println("strFdemo="+strFdemo.getA());
}
}
运行结果:
Obeject类型为:java.lang.Integer
test=12
Obeject类型为:java.lang.String
strFdemo=我是中国人
3. 限制泛型:
我们直接上代码:
 package com.learn.chap06.sec02;
 public class Animal {
     public void say() {
         System.out.println("它是动物");
     }
 }
 package com.learn.chap06.sec02;
 public class Dog extends Animal{
     @Override
     public void say() {
         // TODO Auto-generated method stub
         System.out.println("它是一只狗");
     }
 }
 package com.learn.chap06.sec02;
 public class Cat extends Animal{
     @Override
     public void say() {
         // TODO Auto-generated method stub
         System.out.println("它是一只猫");
     }
 }
 package com.learn.chap06.sec02;
 public class Demo<T extends Animal>{
     private T ob;
     public Demo(T ob) {
         super();
         this.ob = ob;
     }
     public T getOb() {
         return ob;
     }
     public void setOb(T ob) {
         this.ob = ob;
     }
     public void print(){
         System.out.println("T的类型是:"+ob.getClass().getName());
     }
 }
package com.learn.chap06.sec02;
/**
* 限制泛型
* @author Administrator
*
*/
public class Test {
public static void main(String[] args) {
Demo<Dog> demo = new Demo<Dog>(new Dog());
//demo.say();
demo.print(); //Demo<Integer> demo = new Demo<Integer>(new Dog()); // 由于泛型定义Demo类的类型必须为Animal或其子类Dog和Cat,而Integer不是Animal的子类,所以类型被限制,即:限制泛型,导致编译报错
Demo<Animal> demo2 = new Demo<Animal>(new Cat());
demo2.print(); Demo<Cat> demo3 = new Demo<Cat>(new Cat());
demo3.print(); }
}
运行结果:
T的类型是:com.learn.chap06.sec02.Dog
T的类型是:com.learn.chap06.sec02.Cat
T的类型是:com.learn.chap06.sec02.Cat
4. 通配符泛型:
我们直接上代码:
package com.learn.chap06.sec03; import com.learn.chap06.sec02.Animal;
import com.learn.chap06.sec02.Cat;
import com.learn.chap06.sec02.Demo;
import com.learn.chap06.sec02.Dog; public class Test1 {
/**
* 通配符泛型
* @param demo
*/
public static void take(Demo<?> demo){ // <?> 即为:通配符泛型
demo.print();
} public static void main(String[] args) {
Demo<Dog> demo1 = new Demo<Dog>(new Dog());
take(demo1); Demo<Cat> demo2 = new Demo<Cat>(new Cat());
take(demo2); Demo<Animal> demo3 = new Demo<Animal>(new Animal());
take(demo3);
}
}
运行结果:
T的类型是:com.learn.chap06.sec02.Dog
T的类型是:com.learn.chap06.sec02.Cat
T的类型是:com.learn.chap06.sec02.Animal
5. 泛型方法:
 package com.learn.chap06.sec04;
 public class Test {
     /**
      * 泛型方法
      * @param t
      */
     public  static <T> void f(T t) {
         System.out.println("T的类型是:"+t.getClass().getName());
     }
     public static void main(String[] args) {
         f(1);
         f("hello");
         f(1.0f);
         f(new Object());
     }
 }
运行结果:
T的类型是:java.lang.Integer
T的类型是:java.lang.String
T的类型是:java.lang.Float
T的类型是:java.lang.Object
现在使用泛型没问题了吧!呵呵
Java之泛型的更多相关文章
- [改善Java代码]Java的泛型是类型擦除的
		泛型可以减少强制类型的转换,可规范集合的元素类型,还可以提高代码的安全性和可读性,正是因为有了这些优点,自从Java引入泛型之后,项目的编码规则上便多了一条,优先使用泛型. Java泛型(Generi ... 
- Java 中泛型的全面解析(转)
		Java泛型(generics) 是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(type parameter).声明的类型参数在使用时用具体的类型来替换.泛型最主要的应用是在J ... 
- Java中泛型 类型擦除
		转自:Java中泛型是类型擦除的 Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就是说所有泛型参数类 ... 
- Java 泛型 Java使用泛型的意义
		Java 泛型 Java使用泛型的意义 @author ixenos 直接意义 在编译时保证类型安全 根本意义 a) 类型安全问题源自可复用性代码的设计,泛型保证了类型安全的复用模板 b) 使用复用性 ... 
- 跟着刚哥梳理java知识点——泛型(十三)
		一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: public class GenericTest { public static void main(String[] a ... 
- 【Java】泛型学习笔记
		参考书籍 <Java核心技术:卷1> 泛型, 先睹为快 先通过一个简单的例子说明下Java中泛型的用法: 泛型的基本形式类似于模板, 通过一个类型参数T, 你可以"私人定制&qu ... 
- [转] Java 的泛型擦除和运行时泛型信息获取
		原文链接 https://my.oschina.net/lifany/blog/875769 前言 现在很多程序员都会在简历中写上精通 Java.但究竟怎样才算是精通 Java 呢?我觉得不仅要熟练掌 ... 
- Java 容器 & 泛型:五、HashMap 和 TreeMap的自白
		Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Java 容器的文章这次应该是最后一篇了:Java 容器 系列. 今天泥瓦匠聊下 Maps. 一.Ma ... 
- 【译】9. Java反射——泛型
		原文地址:http://tutorials.jenkov.com/java-reflection/generics.html ===================================== ... 
- Java“禁止”泛型数组
		Java“禁止”泛型数组 原文:https://blog.csdn.net/yi_Afly/article/details/52058708 1. 泛型定义泛型编程是一种通过参数化的方式将数据处理与数 ... 
随机推荐
- 避免Gson使用时将一些字符自动转换为Unicode转义字符
			// 避免Gson使用时将一些字符自动转换为Unicode转义字符 public static Gson gson = new GsonBuilder().disableHtmlEscaping(). ... 
- MySQL乱码问题及字符集实战
			mysql> create database oldboy;Query OK, 1 row affected (0.01 sec) mysql> mysql> mysql> s ... 
- centos 使用yum安装MySQL 5.7
			想在centos上安装一个MySQL,使用yum install mysql-server 安装提示仓库没有包,也是醉了. 找了很多博客,发现一个很好用的,推荐给大家. 地址:https://blog ... 
- 【scala】迭代器
			如何访问集合呢?我们首先想到的是使用for循环来访问,还有一种方法是通过迭代器来访问. 在Scala中,迭代器(Iterator)不是一个集合,但是,提供了访问集合的一种方法. 迭代器包含两个基本的操 ... 
- nivicat premium连接阿里云数据库
			1.首先打开Navicat,文件>新建连接>MySQL连接,其他的如一图所示 其中: 连接名:自己取一个名字 主机名:填写mysql的地址 用户名:mysql的登录的用户名 密码:登录的密 ... 
- ./startup.sh: /bin/sh^M: bad interpreter: 没有那个文件或目录 解决办法
			这是因为Linux上 的catalina.sh文件格式给修改了,看不出来,这样就必须通过vim编辑下,变为正常的格式,在catalina.sh的命令模式下输入 ( :set ff=unix ),接着 ... 
- 基于openfire+smack即时通讯instant message开发
			前言 Java领域的即时通信的解决方案可以考虑openfire+spark+smack.当然也有其他的选择. Openfire 是基于Jabber协议(XMPP)实现的即时通信服务器端版本,目前建议使 ... 
- AFNetworking网络请求与图片上传工具(POST)
			AFNetworking网络请求与图片上传工具(POST) .h文件 #import <Foundation/Foundation.h> /** 成功Block */ typedef vo ... 
- 任务调度 Spring Task 4(一)
			深入浅出spring task定时任务 在工作中有用到spring task作为定时任务的处理,spring通过接口TaskExecutor和TaskScheduler这两个接口的方式为异步定时任务提 ... 
- 如何创建 Visual Studio 2017 RC 离线安装包
			创建 Visual Studio 的离线安装计划 首先下载相应版本的可执行文件,例如:vs_community.exe.vs_enterprise.exe 或 vs_professional 在 cm ... 
