数组可以在创建的时候就指定存放的数据类型,这样放入不同类型的时候就会发生编译错误。
而集合却可以存储多种不同类型,这样的话如果是遍历的时候在集合中装了好多不同的数据类型的时候,十分容易发生类型转换错误
集合也模仿数组的做法,在创建对象的时候明确数据的数据类型
这种技术被称为:泛型 泛型是一种把类型明确的工作推迟到创建对象或者调用方法的时候才明确的特殊的类型。参数化类型,把类型当做参数一样的传递。
格式:<数据类型> 此处的数据类型只能是引用数据类型 好处:
把运行期的问题提前到了编译期间
避免了强制类型转换
优化了程序设计,解决了黄色警告线 泛型的由来:
程序早期使用的是Object代替任意引用数据类型,但是在实际用用中会出现类型转换问题,索引JDK5引入了泛型来解决这个安全性问题
package com.Generic;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/*
* 定义了一个List集合,先后加入了两个字符串类型的值和一个Integer类型的值,这时候,此时list的默认类型为Object
* 在之后的循环中,由于忘记之前在list中也加入了Integer,引发类型转换异常
* 为了让集合能够记住集合内元素各种类型,且能达到只要编译期不出现问题,运行期间就不会出现类型转换异常,引入了
* 泛型
*
* 什么是泛型?
* 泛型,即“参数化类型”。一提到参数,最熟悉的就是已定义方法时有形参,然后调用此方法传递实参。那么参数化类型怎
* 么理解呢?顾名思义,就是将原来的类型由具体的类型参数化,类似于方法中的变量参数,此时类型也可以定义成参数形
* 式(可以称之为类型形参),然后在使用时传入具体的类型(类型实参)
*
*
* 采用泛型写法后,在test02中想加入Integer类型会出现编译错误,通过List<String>,直接限定了list集合中只能含有
* String类型的元素,从而在遍历的时候不需要进行强制类型转换,因为此时,集合能够记住元素的类型,编译期已经可以
* 确定它是String类型了
*
*结合上面的泛型定义,我们知道在List<String>中,String是形式参数,也就是说,相应的List接口中肯定含有类型的形参。
*而且get()方法的返回结果也是直接此形参类型(也就是对应的传入的类型实参)。
*
*可以看到,在List接口中采用泛型化定义后,<E>中的E表示类型参数,可以接受具体的类型实参,接口定义中,凡是出现E的
*地方均表示相同的接受外部的类型实参
*/
public class GenericTest {
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("guo");
list.add("liu");
//list.add(100);这里就无法添加进入Integer类型的元素了 for(int i=0;i<list.size();i++){
String name=list.get(i);//这里不需要强制转换了
System.out.println("name:"+name);
}
} public void test01(){
//引出泛型
List list=new ArrayList();
list.add("guo");
list.add("liu");
list.add(100); for(int i=0;i<list.size();i++){
String name=(String) list.get(i);
System.out.println("name:"+name);
}
}
public void test02(){
//第一次使用泛型
List<String> list=new ArrayList<String>();
list.add("guo");
list.add("liu");
//list.add(100);这里就无法添加进入Integer类型的元素了 for(int i=0;i<list.size();i++){
String name=list.get(i);//这里不需要强制转换了
System.out.println("name:"+name);
}
}
} interface Listyuanma<E> extends Collection<E> { int size(); boolean isEmpty(); boolean contains(Object o); Iterator<E> iterator(); Object[] toArray(); <T> T[] toArray(T[] a); boolean add(E e); boolean remove(Object o); boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); boolean addAll(int index, Collection<? extends E> c); boolean removeAll(Collection<?> c); boolean retainAll(Collection<?> c); void clear(); boolean equals(Object o); int hashCode(); E get(int index); E set(int index, E element); void add(int index, E element); E remove(int index); int indexOf(Object o); int lastIndexOf(Object o); ListIterator<E> listIterator(); ListIterator<E> listIterator(int index); List<E> subList(int fromIndex, int toIndex);
} package com.Generic;
/*
* 从前面了解了泛型的具体运作过程。也知道了接口、类、方法可以使用泛型去定义以及相关的使用。是的,在具体使用时候,可以分为泛型接口,泛型类,泛型方法
*
* 在泛型接口、泛型类和泛型方法的定义过程中,我们常用的如T K V E等形式的参数常常用于表示泛型形参,由于接受外部使用的时候传入的类型实参。那么对于传入的不同类型参数,
* 生成的相应对象实例的类型是不是不一样的呢?
*
* 下面的例子,我们发现,在使用泛型类的时候,虽然传入了不同的泛型实参,但是并没有真正意义上生成不同的类,传入不同泛型参数的泛型类在内存中只有一个,即还是原来的最基
* 本的类型,当然,在java中可以理解成多个不同的泛型类型
*
* 究其原因,在于java中泛型这一概念提出的目的,导致其只是作用于代码编译阶段,在编译过程中,对于正确的泛型检查泛型结果后,会将泛型的相关信息擦除。也就是说,成功编译
* 后的class文件中是不包含任何泛型信息的,泛型信息不回进入到运行阶段。
*
* 对比总结成一句话:泛型类型在逻辑上看已堪称多个不同的类型,实际上都是相同的基本类型
*/
public class GenericTest02 {
public static void main(String[] args) {
Box<String> name=new Box<String>("corn");
Box<Integer> age=new Box<Integer>(712);
//System.out.println(name.getData()); System.out.println("name class:"+name.getClass());
System.out.println("age class:"+age.getClass());
System.out.println(name.getClass()==age.getClass());
}
} /*GenericTest02 的class文件反编译后
public class GenericTest02
{ public GenericTest02()
{
} public static void main(String args[])
{
Box name = new Box("corn");
Box age = new Box(Integer.valueOf(712));
System.out.println((new StringBuilder("name class:")).append(name.getClass()).toString());
System.out.println((new StringBuilder("age class:")).append(age.getClass()).toString());
System.out.println(name.getClass() == age.getClass());
}
} */ class Box<T>{
private T data; public Box(){ } public Box(T data){
this.data=data;
} public T getData(){
return data;
}
} package com.Generic;
/*
* 通过前面的结论我们知道,Box<Number>和Box<Intefer>实际上都是Box类型,现在需要探讨一个问题,那么在逻辑上
* ,类似于Box<Number>和Box<Integer>是否可以看成是具有父子关系的泛型呢?
*
* 我们发现,在age调用getData(Box<Number> data)会报错:The method getData(Box<Number>) in the type GenericTest03 is not applicable for the arguments (Box<Integer>)
* 显然,我们知道,Box<Number>在逻辑上不能视为Box<Integer>的父类,原因何在呢?
*
* 在这个例子中出现错误,我们可以使用反证法来说明。
*
* 假如Box<Number>在逻辑上可以视为Box<Integer>的父类,那么就不会报错了。那么问题来了,通过getDate取出来的 到底是什么类型呢?Integer、Number?且由于在编程过程中的顺序不可控,
* 导致在必要的时候必须要进行类型判断,然后进行强制类型转换,显然,这与泛型的理念相矛盾。因此,在逻辑上Box<Number>不能视为Box<Integer>的父类
*
* 解决问题:
* 定义一个新的函数,方法的重载?这与java中的多态理念是相违背的。因此我们需要一个用来表示同时是Box<Integer>和Box<Number>父类的一个引用类型,由此,类型通配符应运而生。
*
* 类型通配符一般使用?代替具体的参数类型。注意了,此处是类型实参,而不是类型形参!且Box<?>在逻辑上是Box<Integer>、Box<Integer>等所有Box<具体类型实参>的父类。由此,我们仍然
* 可以定义泛型方法来完成此需求。
*
* 有时候,我们可能对类型实参有进一步限制?此时可能用到通配符上限和通配符下限
* Box<? extends Number>代表Box的泛型只能是Number和Number的子类
* Box<? super Number>代表Box的泛型只能是Number和Number的父类
*
* java泛型主要是用在集合中,并没有泛型数组一说
*/
public class GenericTest03 {
public static void main(String[] args) {
Box<Number> name=new Box<Number>(99);
Box<Integer> age=new Box<Integer>(712);
Box<Double> h=new Box<Double>(0.2);
Box<String> s=new Box<String>("12s");
getData03(name);
getData03(age);
//getData03(h); 报错,类型
//getData03(s); 报错,类型
}
public void test01(){
Box<Number> name=new Box<Number>(99);
Box<Integer> age=new Box<Integer>(712);
Box<Double> h=new Box<Double>(0.2);
Box<String> s=new Box<String>("12s");
getData02(name);
getData02(age);
getData02(h);
//getData02(s); 这里会报错
} public void test02(){
Box<Number> name=new Box<Number>(99);
Box<Integer> age=new Box<Integer>(712);
Box<Double> h=new Box<Double>(0.2);
Box<String> s=new Box<String>("12s");
getData(name);
getData(age);
getData(h);
getData(s);
}
public static void getData00(Box<Number> data){
System.out.println("data:"+data.getData());
}
//Box的所有泛型
public static void getData(Box<?> data){
System.out.println("data:"+data.getData());
} //限制只能是泛型为Number和Number的子类泛型
public static void getData02(Box<? extends Number> data){
System.out.println("data:"+data.getData());
}
//限制只能是泛型为Integer和Integer的父类泛型
public static void getData03(Box<? super Integer> data){
System.out.println("data:"+data.getData());
}
}
package jdk5的新特性;

/*
* 可变参数
* 举个例子:如果需要计算一组数的和,但不知道计算的数有多少个,那怎么办呢?
* 使用方法重载? 这是不现实的。
* 所以我们有了可变参数
* 形式: 数据类型...变量名 表示接受n个该类型的变量
* 可变参数的方式接受到了数据怎么使用呢?
* 通过查看源码,反编译的方式。我们发现,可变参数其实本质上是一个指定类型数组类型的参数,
* 在调用方法的时候构建固定长度的固定类型数组,然后传入方法
* 使用可变参数的时候需要注意:
* 可变参数一般放在参数列表的最后面。可变参数的形参名表示的是一个数组名
*/
public class ChangeParam {
public static void main(String[] args) {
System.out.println(getCount(1,2,3));
System.out.println(getCount(1,2));
System.out.println(getCount());
System.out.println(getCount(new int[]{1,2,3}));
}
/*public int getCount(int a,int b){
return a+b;
}
public int getCount(int a,int b,int c){
return a+b+c;
}*/
//...
public static int getCount(int...in){
int c=0;
for(int s:in){
c+=s;
}
//return 0;
return c;
}
} package jdk5的新特性; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; public class ArrayAsList {
//发现Arrays的asList使用的是可变参数
//public static <T> List<T> asList(T... a)
public static void main(String[] args) {
ArrayList<Integer> al=new ArrayList<Integer>();
List ss= Arrays.asList(12,24,12);
// ss.add(3);
//ss.remove(3); 通过它获得的实质上是一个数组,只能修改内容,不能操作长度
ss.set(2, 23);
System.out.println(ss); }
}
package jdk5的新特性;

//import java.sql.Date;

public class StaticImport {
public static void main(String[] args) {
//System.out.println(Date.valueOf("12"));
//System.out.println(java.sql.Date.valueOf("12"));
}
}
/*
* 原来的导入都是导入的是类。使用import 包名.类名
* 如果需要不导入类,就需要这样:java.sql.Date.valueOf("12")
* jdk5提供了静态导入的功能:
* 在类名的上面导入静态方法,暂时没找到例子
* import 类名.方法名格式。 注意方法必须是静态方法
* 当静态导入的方法与类中的方法重名的时候,必须使用这种形式java.sql.Date.valueOf("12")
*/

JDK5的新特性:泛型、可变参数、静态导入的更多相关文章

  1. JDK5的新特性之可变参数&Arrays.asList()方法

    [代码] package com.hxl; import java.util.Arrays; import java.util.List; public class Test { public sta ...

  2. JDK5新特性之 可变参数的方法

    可变参数的方法:不知道这个方法该定义多少个参数 注意: > 参数实际上是数组 > 必须写在参数列表最后一个 package cn.itcast.day24.varparam; import ...

  3. jdk1.5新特性之------->可变参数

    /* jdk1.5新特性之------->可变参数 需求: 定义一个函数做加法功能(函数做几个数据 的加法功能是不确定). 可变参数的格式: 数据类型... 变量名 可变参数要 注意的细节: 1 ...

  4. JDK5新特性:可变参数方法

    JDK1.5增加可变参方法,其定义格式为: 访问修饰符 返回值类型 方法标识符(参数类型 参数标识符1,参数类型 参数标识符2,参数类型...参数标识符){} 如可能要定义一个求和功能的方法,但求和的 ...

  5. C++11新特性之五——可变参数模板

    有些时候,我们定义一个函数,可能这个函数需要支持可变长参数,也就是说调用者可以传入任意个数的参数.比如C函数printf(). 我们可以这么调用. printf(); 那么这个函数是怎么实现的呢?其实 ...

  6. JDK5 新特性之 可变参数的方法(2)---asList

    > Arrays.asList(T - a)方法的使用 >UnsupportedOperationException分析     Arrays.asList(T - a)方法的使用 pac ...

  7. java新特性之可变参数

    public class NewDemo01 {     public static void main(String[] args) {         System.out.print(" ...

  8. Java JDK5新特性-泛型

    2017-10-30 22:47:11 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质 ...

  9. Javaweb学习笔记——(七)——————myexlipse基本使用、jdk5.0新特性及反射讲解

    1.debug调试模式: *使用这种模式,调试程序(看到程序运行停止在这一行) -显示出来行号 -双击左边,出现一个圆点,表示设置了一个断点 *使用debug as方式,运行程序 -特使是否进入到调试 ...

随机推荐

  1. Mysql数据库安装与配置

    先介绍下dql,dml,ddl,dcl: 安装: 加上这一行: 接下来把mysql设置成随系统自动启动: 开放3306端口(如果是阿里云服务器需要修改安全规则而不是如下): 或者 这里注意,有时候没有 ...

  2. 101-advanced-React易用性,概述

    React完全支持构建可访问的网站,通常使用标准的HTML技术. 1.可访问小部件 ARIA文档包含用于构建完全可访问的JavaScript小部件的技术. JSX完全支持所有aria- * HTML属 ...

  3. EOS 的网站及资料doc

    https://github.com/EOSIO/Documentation/blob/master/zh-CN/Roadmap.md https://bytemaster.github.io/bit ...

  4. mysql数据库访问权限限制设置

    ---只能本地访问,设置随意访问 update user set host='%' where host='localhost': flush privileges; ---随意访问,设置只能本地访问 ...

  5. 主从同步DNS(BIND)

    看着别人搭建很简单,其实到自己做的时候需要考虑更多的问题. 1.环境 1)操作系统最好一样,配置一样 2)关闭防火墙,selinux,时间要同步(我就是用的纽约的时区,同步中国的时间,虽然时间是相同的 ...

  6. (转)SSIS_数据流转换(Union All&合并联接&合并)

    Union All : 与sql语言 Union All 一样,不用排序,上下合并多个表.Union All转换替代合并转换:输入输出无需排序,合并超过两个表 合并联接 : 有左连接.内连接.完全连接 ...

  7. 2017中国大学生程序设计竞赛-哈尔滨站 Solution

    A - Palindrome 题意:给出一个字符串,找出其中有多少个子串满足one-half-palindromic 的定义 思路:其实就是找一个i, j  使得 以i为中轴的回文串长度和以j为中轴的 ...

  8. 466E - Information Graph 巧妙的判断祖先于孩子的关系

    这题说的是给了一个公司员工100000 然后现在又3种操作第一种将y置为x的父亲,第二种操作将文件给第x个人签他签完给他的上司签,一直到没有上司为止,第三种操作问x是否签了第i份文件,然后 我们只要直 ...

  9. JavaScript进阶内容笔记1:各种对象类型判断

    该文章主要用来介绍JavaScript中常用的一些对象检测判断方法,整理资源来自书本和网络,如有错误或说明不详之处,望评论提出,本菜定提名感谢……(本文章知识比较基础,大牛请提些意见再绕道,三克油^_ ...

  10. js 变量、函数提升 与js的预编译有关

    参考网址:http://www.codesec.net/view/178491.html 先简单理解下作用域的概念,方便对变量与函数提升的概念的理解 function foo() { var x = ...