java泛型简单学习

一. 泛型概念的提出(为什么需要泛型)?

首先,我们看下下面这段简短的代码:

//import java.util.List;

public class GenericTest {

    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("语文");
        list.add("数学");
        list.add(100);  //编译错误

        for (int i = 0; i < list.size(); i++) {
            String name = (String) list.get(i); // 1
            System.out.println("name:" + name);
        }
    }
}

定义了一个List类型的集合,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。这是完全允许的,因为此时list默认的类型为Object类型。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他编码原因,很容易出现类似于//1中的错误。因为编译阶段正常,而运行时会出现“java.lang.ClassCastException”异常。因此,导致此类错误编码过程中不易发现。

在如上的编码过程中,我们发现主要存在两个问题:

1.当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。

2.因此,//1处取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现“java.lang.ClassCastException”异常。

那么有没有什么办法可以使集合能够记住集合内元素各类型,且能够达到只要编译时不出现问题,运行时就不会出现“java.lang.ClassCastException”异常呢?答案就是使用泛型。

二.什么是泛型?

泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

看着好像有点复杂,首先我们看下上面那个例子采用泛型的写法。

public static void main(String[] args) {

        List<String> list = new ArrayList<String>();//2

        list.add("语文");
        list.add("数学");
        list.add("英语");
        //list.add(100);//1 编译错误

        //输出
        for(int i=0 ; i<list.size();i++){
            String subjectName = list.get(i);//3
            System.out.println("科目名称:"+subjectName);

        }
    }

1. 程序//1处试图将一个Integer对象添加到list集合中,程序将无法通过编译,报出:
    java.lang.Error: Unresolved compilation problem
    因为list只接受String对象作为元素,所以//1处代码在编译时会得到错误提示

2.所以要使用泛型,如程序2处创建一个特殊的List集合:list,这个List集合只能保存字符串对象,不能保存其他类型的对象
   创建这种特殊集合的方式是:在集合接口、类后增加尖括号,尖括号里放一个数据类型,即表示这个集合接口、结合类只能保存特定类型的对象
   如//2处的类型声明,它指定:list不是一个任意的list,而是一个String类型的list,写作List<String>.我们认为list是带一个类型参数的泛型接口

3.程序在//3处不需要进行强制类型转换,因为list对象可以“记住”它的所有集合元素都是String类型

结合上面的泛型定义,我们知道在List<String>中,String是类型实参,也就是说,相应的List接口中肯定含有类型形参。且get()方法的返回结果也直接是此形参类型(也就是对应的传入的类型实参)。

三、JAVA 7泛型的“棱形”写法

在java 7以前,如果使用带泛型的接口、类定义变量,那么调用构造器创建对象时构造器的后面也必须带泛型,则显得有些多余,例如:

List<String> strList = new ArrayList<String>();
Map<String ,Interger> scores = new HashMap<String ,Integer>();

上面两条语句中的粗体代码部分是完全多余的,在java 7以前这是必需的,不能省略。java 7以后,只要给出一对尖括号(<>)即可,java可以
推断出尖括号里应该是什么泛型信息。即上面两条语句可以改为如下形式:

List<String> strList = new ArrayList<>();
Map<String ,Interger> scores = new HashMap<>();

因而简化代码:

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

        list.add("语文");
        list.add("数学");
        list.add("英语");
        //list.add(100);//2

        //输出
        for(int i=0 ; i<list.size();i++){
            String subjectName = list.get(i);//3
            System.out.println("科目名称:"+subjectName);

        }

Double泛型:

   List<Double> list = new ArrayList<>();//2

        list.add(10.1);
        list.add(10.2);
        list.add(10.3);
        //list.add(100);//1

        //输出
        for(int i=0 ; i<list.size();i++){
            Double subjectName = list.get(i);//3
            System.out.println("科目成绩:"+subjectName);

        }

键值对:

java中的map其实就是以键值对形式的存放数据的容器,其常用的实现类主要是哈希map
例如:
Map map = new HashMap();
插入元素:map.put("key", obj); 
移除元素: map.remove("key");
清空: map.clear();

import java.util.HashMap;
import java.util.Map;

Map<String,Double> list = new HashMap<>();//2

        list.put("语文",10.1);
        list.put("数学",10.1);
        list.put("英语",100.0);
         String arr[]={"语文","数学","英语"};

        //输出
        for(int i=0 ; i<list.size();i++){
            Double subjectName = list.get(arr[i]);//必须是键值对
            System.out.println("科目成绩:"+subjectName);

        }
时间: 2024-12-25 20:23:08

java泛型简单学习的相关文章

Java泛型再学习

泛型是对于数据的一种规范,他限定了类.容器.方法可以接受的参数类型,避免参数类型混乱. 一.基本泛型 泛型最常见的地方就是集合,如: -- ArrayList<String>  表示这个集合中只能存放String类型的元素 -- HashMap<String, Object>  表示这个图中只能存放键为String类型,值为Object类型的元素 特别要注意的时,泛型只存在于编译阶段,在程序运行阶段,我们定义的泛型是并不存在的,这种方案叫“擦除”,示例: 1 public clas

Java泛型通配符学习 —— Java Generic&#39;s Wildcards

Java Generic's wildcards is a mechanism in Java Generics aimed at making it possible to cast a collection of a certain class, e.g A, to a collection of a subclass or superclass of A. This text explains how. 理解:Java的泛型通配符机制旨在实现集合的类型转换.例如集合A,转换为A的子类集合或

Java泛型知识学习

一.泛型出现的原因 首先,我们先看一个例子,如下: public class ListErr { public static void main(String[] args) { //创建一个只想保存字符串的List集合 List strList = new ArrayList(); strList.add("Hello World"); strList.add("Good Morning"); strList.add("你好"); //&quo

Java注解简单学习

注解(也被称作元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们在稍后某个时刻可以很方便的使用这些数据,其在一定程度上将元数据与源代码文件结合在一起,而不是保存在外部文档中. 注解使我们可以用将来由编译器测试和验证的格式,存储程序有关的额外信息.注解可以用来生成描述符文件,甚至是新的类定义,并且有助于减轻编写"样板"代码的负担.通过使用注解,将元数据保存在Java源代码中,并利用annotation API为注解构造处理工具来读取注解. Java目前只内置了三种标准注解,以及

java 泛型简单使用

Java泛型学习笔记--Java泛型和C#泛型比较学习(一)

总结Java的泛型前,先简单的介绍下C#的泛型,通过对比,比较学习Java泛型的目的和设计意图.C#泛型是C#语言2.0和通用语言运行时(CLR)同时支持的一个特性(这一点是导致C#泛型和Java泛型区别的最大原因,后面会介绍).C#泛型在.NET CLR支持为.NET框架引入参数化变量支持.C#泛型更类似C++模板,可以理解,C#泛型实际上可以理解为类的模板类.我们通过代码实例来看C# 2.0泛型解决的问题,首先,我们通过一个没有泛型的迭代器的代码示例说起,代码实现如下: interface

java泛型学习和实践(4)

引言 前三节讲述了泛型常见声明及使用,泛型既可以在类上进行声明,也可以在单个方法上进行声明,并分别对这两种情况进行了总结.下面来学习下泛型扩展知识. 延用前面的Runnable接口.Buick类.Ford类.Driver类,新增加一个汽车容器类CarContainer 第一版 代码如下: public interface Runnable { public void run(); } public class Buick implements Runnable { @Override publi

JAVA学习Swing章节按钮组件JButton的简单学习

package com.swing; import java.awt.Container; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.URL; import javax.swing.Icon; import javax.swing.ImageIcon;

java 泛型学习

http://blog.csdn.net/archie2010/article/details/6232228 学习集合框架的时候经常用hasmap<Integer,Integer>就是泛型,c++里面叫模板,其实我是想研究一下迭代器模式的.睡觉,明天再说. 1 import java.util.ArrayList; 2 import java.util.Collection; 3 4 class A< T extends Collection> 5 { 6 private T x