文档章节

Java泛型

PythonJsGo
 PythonJsGo
发布于 2017/08/05 20:09
字数 1558
阅读 15
收藏 1

一、为什么要有泛型(Generic)?
    1. 解决元素存储的安全性问题
    2. 解决获取数据元素时,需要类型强转的问题

    泛型,JDK1.5新加入的,解决数据类型的安全性问题,其主要原理是在类声明时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这样在类声明或实例化时只要指定好需要的具体的类型即可。Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮。

二、使用泛型

三、在集合中使用泛型
    1.对象实例化时不指定泛型,默认为:Object。
    2.泛型不同的引用不能相互赋值。
    3.加入集合中的对象类型必须与指定的泛型类型一致。

    4.静态方法中不能使用类的泛型。

    5.如果泛型类是一个接口或抽象类,则不可创建泛型类的对象。

    6.不能在catch中使用泛型

    7.从泛型类派生子类,泛型类型需具体化

    备注:把一个集合中的内容限制为一个特定的数据类型,这就是generics背后的核心思想。

泛型方法

    方法,也可以被泛型化,不管此时定义在其中的类是不是泛型化的。在泛型方法中可以定义泛型参数,此时,参数的类型就是传入数据的类型。

泛型方法的格式:
[访问权限]  <泛型>  返回类型  方法名([泛型标识 参数名称])  抛出的异常

public class DAO {
    
    public <E>  E get(int id, E e){
        
        E result = null;
        
        return result;
    }
    
}
static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
	for (T o : a) {
		c.add(o);
	}	
}

public static void main(String[] args) {
	Object[] ao = new Object[100];
	Collection<Object> co = new ArrayList<Object>();
	fromArrayToCollection(ao, co);

	String[] sa = new String[20];
	Collection<String> cs = new ArrayList<>();
	fromArrayToCollection(sa, cs);

	Collection<Double> cd = new ArrayList<>();
	// 下面代码中T是Double类,但sa是String类型,编译错误。
	// fromArrayToCollection(sa, cd);
	// 下面代码中T是Object类型,sa是String类型,可以赋值成功。
	fromArrayToCollection(sa, co);  
}

四、泛型和继承的关系

        如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口,G<B>并不是G<A>的子类型!比如:String是Object的子类,但是List<String >并不是List<Object>的子类。

public void testGenericAndSubClass() {
	Person[] persons = null;
	Man[] mans = null;
	// 而 Person[] 是 Man[] 的父类.
	persons = mans;

	Person p = mans[0];

	// 在泛型的集合上
	List<Person> personList = null;
	List<Man> manList = null;
	// personList = manList;(报错)
}

五、通配符

    1.使用类型通配符:? 
        比如:List<?>   ,Map<?,?>
        List<?>是List<String>、List<Object>等各种泛型List的父类。

    2.读取List<?>的对象list中的元素时,永远是安全的,因为不管list的真实类型是什么,它包含的都是Object。

    3.写入list中的元素时,不行。因为我们不知道c的元素类型,我们不能向其中添加对象。
        唯一的例外是null,它是所有类型的成员。
        将任意元素加入到其中不是类型安全的:
        Collection<?> c = new ArrayList<String>();
        c.add(new Object()); // 编译时错误
        因为我们不知道c的元素类型,我们不能向其中添加对象。
        add方法有类型参数E作为集合的元素类型。我们传给add的任何参数都必须是一个未知类型的子类。 因为我们不知道那是什么类型,所以我们无法传任何东西进去。唯一的例外的是null,它是所有类型的成员。另一方面,我们可以调用get()方法并使用其返回值。返回值是一个未知的类型,但是我们知道,它总是一个Object。

public static void main(String[] args) {
	List<?> list = null;
	list = new ArrayList<String>();
	list = new ArrayList<Double>();
	//list.add(3);
	list.add(null);
		
	List<String> l1 = new ArrayList<String>();
	List<Integer> l2 = new ArrayList<Integer>();
	l1.add(“Python");
	l2.add(15);
	read(l1);
	read(l2);  }
	static void read(List<?> list){
		for(Object o : list){
			System.out.println(o);
	}
}

    4.有限制的通配符

<?>

允许所有泛型的引用调用

举例:

<? extends Number>     (无穷小 , Number]

只允许泛型为Number及Number子类的引用调用

 

<? super Number>      [Number , 无穷大)

只允许泛型为Number及Number父类的引用调用

 

<? extends Comparable>

只允许泛型为实现Comparable接口的实现类的引用调用

public static void printCollection3(Collection<? extends Person> coll){
	 
	Iterator<?> iterator  = coll.iterator();
	while(iterator.hasNext()){
		System.out.println(iterator.next());
	}   
}

public static void printCollection4(Collection<? super Person> coll){
	Iterator<?> iterator  = coll.iterator();
	while(iterator.hasNext()){
		System.out.println(iterator.next());
	}  

}

范例:泛型应用


    用户在设计类的时候往往会使用类的关联关系,例如,一个人中可以定义一个信息的属性,但是一个人可能有各种各样的信息(如联系方式、基本信息等),所以此信息属性的类型就可以通过泛型进行声明,然后只要设计相应的信息类即可。

 
public interface Info{		// 只有此接口的子类才是表示人的信息

}

public class Contact implements Info{	// 表示联系方式
	private String address ;	// 联系地址
	private String telephone ;	// 联系方式
	private String zipcode ;	// 邮政编码
	
	public Contact(String address,String telephone,String zipcode){
		this.address = address;
		this.telephone = telephone;
		this.zipcode = zipcode;
	}
	
	public void setAddress(String address){
		this.address = address ;
	}
	public void setTelephone(String telephone){
		this.telephone = telephone ;
	}
	public void setZipcode(String zipcode){
		this.zipcode = zipcode;
	}
	public String getAddress(){
		return this.address ;
	}
	public String getTelephone(){
		return this.telephone ;
	}
	public String getZipcode(){
		return this.zipcode;
	}
	
	@Override
	public String toString() {
		return "Contact [address=" + address + ", telephone=" + telephone
				+ ", zipcode=" + zipcode + "]";
	}
	
}

public class Introduction implements Info{
	private String name ;		// 姓名
	private String sex ;		// 性别
	private int age ;			// 年龄
	
	public Introduction(String name,String sex,int age){
		this.name = name;
		this.sex = sex;
		this.age = age;
	}
	
	public void setName(String name){
		this.name = name ;
	}
	public void setSex(String sex){
		this.sex = sex ;
	}
	public void setAge(int age){
		this.age = age ;
	}
	public String getName(){
		return this.name ;
	}
	public String getSex(){
		return this.sex ;
	}
	public int getAge(){
		return this.age ;
	}
	
	@Override
	public String toString() {
		return "Introduction [name=" + name + ", sex=" + sex + ", age=" + age
				+ "]";
	}
	
}

public class Person<T extends Info>{
	
	private T info ;
	
	public Person(T info){		// 通过构造方法设置信息属性内容
		this.info = info;
	}
	public void setInfo(T info){
		this.info = info ;
	}
	public T getInfo(){
		return info ;
	}
	
	@Override
	public String toString() {
		return "Person [info=" + info + "]";
	}
	
//	public String toString(){	// 覆写Object类中的toString()方法
//		return this.info.toString() ;
//	}
}

public class GenericPerson{
	public static void main(String args[]){
		Person<Contact> per = null ;		// 声明Person对象
		per = new Person<Contact>(new Contact("北京市","01088888888","666666")) ;
		System.out.println(per);
		
		Person<Introduction> per2 = null ;		// 声明Person对象
		per2 = new Person<Introduction>(new Introduction("王尼玛","男",27));
		System.out.println(per2) ;
	}
}

  GitHub地址:https://github.com/leebingbin/  

© 著作权归作者所有

上一篇: Java常用类
下一篇: Java反射机制
PythonJsGo
粉丝 32
博文 104
码字总数 155493
作品 0
朝阳
高级程序员
私信 提问

暂无文章

golang-字符串-地址分析

demo package mainimport "fmt"func main() {str := "map.baidu.com"fmt.Println(&str, str)str = str[0:5]fmt.Println(&str, str)str = "abc"fmt.Println(&s......

李琼涛
今天
4
0
Spring Boot WebFlux 增删改查完整实战 demo

03:WebFlux Web CRUD 实践 前言 上一篇基于功能性端点去创建一个简单服务,实现了 Hello 。这一篇用 Spring Boot WebFlux 的注解控制层技术创建一个 CRUD WebFlux 应用,让开发更方便。这里...

泥瓦匠BYSocket
今天
6
0
从0开始学FreeRTOS-(列表与列表项)-3

FreeRTOS列表&列表项的源码解读 第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像。 在FreeRTOS中,列表与列表项使用得非常多,是FreeRTOS的一个数...

杰杰1号
今天
4
0
Java反射

Java 反射 反射是框架设计的灵魂(使用的前提条件:必须先得到代表的字节码的 Class,Class 类 用于表示.class 文件(字节码)) 一、反射的概述 定义:JAVA 反射机制是在运行状态中,对于任...

zzz1122334
今天
5
0
聊聊nacos的LocalConfigInfoProcessor

序 本文主要研究一下nacos的LocalConfigInfoProcessor LocalConfigInfoProcessor nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java p......

go4it
昨天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部