面向对象,Java泛型篇

一、Java泛型入门基础

1、 泛型历史:集合中可以存储任意类型对象,但是在取出时,如果要使用具体对象的特有方法时,需要进行向下转型,如果存储的对象类型不一致,在转型过程中就会出现ClassCastException异常。这样就给程序带来了不安全性。

在jdk1.5以后就有了解决方案——泛型技术:在存储元素时,就不允许存储不同类型的元素。存储了就编译失败。 所以就需要在存储元素时,在容器上明确具体的元素类型,这其实和数组定义很像。

2、优势:1)将运行时期的ClassCastException异常转移到了编译时期,进行检查,并以编译失败来体现。 这样有利于程序员尽早解决问题。

2)避免了向下转型(强转)的麻烦。

3、在什么情况下使用泛型呢?

只要在使用类或者接口时,该类或者接口在api文当描述时都带着<>,就需要在使用时定义泛型。

其实,泛型无非就是通过<>定义了一个形式参数,专门用于接收具体的引用类型。在使用时,一定要传递对应的实际参数类型。

集合中泛型的应用特别多见。

二、Java泛型使用

使用泛型的动机举例(以集合为例):

class MySet:(自行写的MySet,实现的Java泛型)

public class MySet<E> {
	private Object[] objs=new Object[0];
	public boolean add(E obj){
		if(contains(obj)){
			return false;
		}
		Object tempObjs[] = new Object[objs.length+1];
		System.arraycopy(objs, 0, tempObjs, 0, objs.length);
		tempObjs[objs.length] = obj;
		objs = tempObjs;
		return true;
	}

	public boolean contains(E obj){
		for(Object o:objs){
			if(o.equals(obj)){
				return true;
			}
		}
		return false;
	}
	public Object[] getAll(){
		return objs;
	}
	public int size(){
		return objs.length;
	}
}

测试class:

import java.util.ArrayList;
import java.util.Iterator;
public class GenericDemo2 {
	public static void main(String[] args) {
//		MySet<String> set = new MySet<String>();
//		set.add("abcd");
//		set.add(8);//编译出错

//		MySet<Integer> set = new MySet<Integer>();
//		set.add("abcd");//编译出错
//		set.add(8);
	}
}

注意:当一个变量被声明为泛型时,只能被实例变量和方法调用,而不能被静态变量和方法调用。原因很简单,参数化的泛型是一些实例。静态成员是被类的实例和参数化的类所共享的,所以静态成员不应该有类型参数和他们关联。

三、Java泛型类

1、概念:当一个类要操作的引用数据类型不确定的时候,可以将该类型定义一个形参。用到的这类时,由使用者来通过传递类型参数的形式,来确定要操作的具体的对象类型。这意味着在定义这个类时,需要在类上定义形参,用于接收具体的类型实参。这就是将泛型定义在类上,即泛型类。

2、什么时候使用泛型类呢?

只要类中操作的引用数据类型不确定的时候,就可以定义泛型类。 有了泛型类,省去了曾经的强转和类型转换异常的麻烦。

代码示例:

/*
 * 泛型类的演示
 */
public class GenericDemo2 {
	public static void main(String[] args) {
		MyVessel<Worker> u = new MyVessel<Worker>();
		//u.setObject(new Student());//不行,u中存放的是Worker,实参只能是Worker类型
		u.setObject(new Worker());
		Worker w = u.getObject();
		System.out.println(w);

		MyVessel<Student> v = new MyVessel<Student>();
		//v.setObject(new Worker());//不行,实参只能是Student类型
	}

}
class MyVessel<E>{ //从语法上讲把“E”取成别的名字如“QQ”也是可以的,但不规范。
	private E obj;
	public void setObject(E obj){
		this.obj = obj;
	}
	public E getObject(){
		return obj;
	}
}
class Student{
	String profession;
}
class Worker{
	String company;
}

四、Java泛型方法

1、泛型方法的定义(与类的泛型捆绑)

方法要操作的类型不确定的,但是和调用该方法的对象指定的类型是一致。

2、泛型方法的定义(独立于类的泛型)

方法要操作的类型不确定的,而且不一定和调用该方法的对象指定的类型是一致。

3、泛型方法的定义(静态方法的泛型)

静态方法不能访问类上定义的泛型,因为它没有对象。如果静态方法需要泛型,该泛型只能定义在方法上。

代码示例:

class Demo<W>{
	//方法上的泛型和类的一致,或者说依赖于类的泛型
	public void show(W w){
		System.out.println("show:"+w.toString());
	}
	//不带泛型,不安全。因为在调用方可以把该方法的返回值强转成其它类型,从而出现强转异常
	public Object myprint0(Object a){
		System.out.println("myprint:"+a);
		return a;
	}
	//方法带泛型,但要求和类的泛型相互独立。可以限定返回类型和方法的实参相同,更安全,而且不用强转。
	public <A> A myprint(A a){
		System.out.println("myprint:"+a);
		return a;
	}
	//静态方法带泛型,泛型一定要独立于类,因为它没有对象。
	public static <A> A myprint2(A a){
		System.out.println("myprint:"+a);
		return a;
	}
}

五、Java泛型接口

这个不好解释直接代码示例了:

interface Inter<V>{
	public abstract V show(V v);
}
//实现泛型接口的类的定义。 方法中的参数类型和类声明实现接口时指定的类型一致,且已经确定为String!-----本例假设我们写这个类的时候知道该类就是专门处理String型数据的
class InterImpl implements Inter<String>{
	@Override
	public String show(String s) {
		System.out.println(s);
		return s;
	}
}
//实现泛型接口的类的定义。 方法中的参数类型和类声明实现接口时指定的类型一致,但不确定!-----本例假设我们写这个类的时候不知道该类是处理什么类型的数据的,但有一点确定:声明类对象时指定什么类型(泛型的实参),show方法就处理该类型
class InterImpl2<C> implements Inter<C>{
	@Override
	public C show(C s) {
		System.out.println(s);
		return s;
	}
}

六、Java泛型高级

(PS:关于Java泛型的高级应用,最低要求:虽然自己不一定能写出这样类似的定义,但是你必须会使用或调用(其他程序员或API中已经采用这种技术写的类或方法),所以这里只做最简单的介绍,有兴趣的博友可以去深入学习,博主能力有限,嘿嘿。。)

1、泛型的通配符:?

当操作的不同容器中的类型都不确定的时候,而且使用的都是元素从Object类中继承的方法, 这时泛型就用通配符?来表示即可。(助理解的比方: 泛型中的多态应用)

2、泛型的限定:

对操作的类型限制在一个范围之内。比如:定义一个功能,只操作Person类型或者Person的子类型。这时可以用:

? extends E:接收E类型或者E的子类型。这就是上限。

? super E:   接收E类型或者E的父类型。 这就是下限。

一般情况下:

只要是往容器中添加元素时,使用上限。 ? extends E

只要是从容器中取出元素时,是用下限。 ? super E

高级只有这么多,博友可以去API中看看这种情况,例如:Collection

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-20 14:55:53

面向对象,Java泛型篇的相关文章

赢在面试之Java泛型篇(十二)

139. Java中的泛型是什么 ? 使用泛型的好处是什么? 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数. 好处: 1.类型安全,提供编译期间的类型检测 2.前后兼容 3.泛化代码,代码可以更多的重复利用 4.性能较高,用GJ(泛型JAVA)编写的代码可以为java编译器和虚拟机带来更多的类型信息,这些信息对java程序做进一步优化提供条件. 140,Java的泛型是如何工作的 ? 什么是类型擦除 ?如何工作? 1.类型检查:在生成字节

第10篇-JAVA 集合框架-JAVA 泛型

第10篇-JAVA 集合框架-JAVA 泛型 每篇一句 :所有的不甘,都是因为还心存梦想 初学心得: 不是每件事都注定会成功,但是每件事都值得一试 (笔者:JEEP/711)[JAVA笔记 | 时间:2017-04-15| JAVA 集合框架/JAVA 泛型 ] 1.JAVA 集合框架概念 通俗的说,集合就是一个存放数据的容器,准确的说,就是放数据对象引用的容器 数组和集合都是容器,有何不同? 数组长度固定,集合长度可变 数组只能存放相同类型的数据,集合可以存放不同类型的数据 数组可存放简单数据

java 第十一天 面向对象(高级篇之接口、对象的多态性,instanceof)

接口的基本概念:接口的访问权限是public,关键字interface,子类通过implements关键字实现接口.一个子类可以同时实现多个接口. 对象的多态性: 两种体现形式:(1)方法的重载与覆写.(2)对象的多态性. 对象的多态性分两种: (1)向上转型:子类对象--→父类对象 (2)向下转型:父类对象--→子类对象 java中可以使用instanceof关键字判断对象到底是哪个类的实例 java 第十一天 面向对象(高级篇之接口.对象的多态性,instanceof),码迷,mamicod

java泛型探索——介绍篇

1. 泛型出现前后代码对比 先来看看泛型出现前,代码是这么写的: List words = new ArrayList(); words.add("Hello "); words.add("worlds!"); String s = (String) words.get(0) + (String) words.get(1); System.out.println(s.equals("Hello worlds!")); 而泛型出现后无需做显式转换:

Java面试题-泛型篇

139. Java中的泛型是什么 ? 使用泛型的好处是什么? 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数. 好处: 1.类型安全,提供编译期间的类型检测 2.前后兼容 3.泛化代码,代码可以更多的重复利用 4.性能较高,用GJ(泛型JAVA)编写的代码可以为java编译器和虚拟机带来更多的类型信息,这些信息对java程序做进一步优化提供条件. 140,Java的泛型是如何工作的 ? 什么是类型擦除 ?如何工作? 1.类型检查:在生成字节

Java泛型简明教程

Java泛型简明教程 博客分类: Java综合 JavaApple数据结构CC++ Java泛型简明教程 本文是从 Java Generics Quick Tutorial 这篇文章翻译而来. 泛型是Java SE 5.0中引入的一项特征,自从这项语言特征出现多年来,我相信,几乎所有的Java程序员不仅听说过,而且使用过它.关于Java泛型的教程,免费的,不免费的,有很多.我遇到的最好的教材有: The Java Tutorial Java Generics and Collections ,

初识java泛型

1 协变数组类型(covariant array type) 数组的协变性: if A IS-A B then A[] IS-A B[] 也就是说,java中的数组兼容,一个类型的数组兼容他的子类类型数组. 协变数组好处:使得代码的灵活性更强. 协变数组的坏处:过于灵活导致类型混乱,比如: Peron[] arr = new Employee[5]; //Employee IS-A Person 可以执行 arr[0] = new Student();// Student IS-A Person

Java总结篇系列:java.lang.Object

从本篇开始,将对Java中各知识点进行一次具体总结,以便对以往的Java知识进行一次回顾,同时在总结的过程中加深对Java的理解. Java作为一个庞大的知识体系,涉及到的知识点繁多,本文将从Java中最基本的类java.lang.Object开始谈起. Object类是Java中其他所有类的祖先,没有Object类Java面向对象无从谈起.作为其他所有类的基类,Object具有哪些属性和行为, 是Java语言设计背后的思维体现. Object类位于java.lang包中,java.lang包包

Java泛型的协变

在上篇<Java泛型的基本使用>这篇文章中遗留下面问题,即将子类型也能加入到父类型的泛型中.要实现这样的功能必须借助于协变. 实验准备 如今在上篇文章展示的Decorator类型的基础上,添加一些代码,如代码清单1所看到的. 代码清单1 /** * * 描 述:Exp2使用br/> * 作 者:jiaan.gja<br/> * 历 史: (版本号) 作者 时间 凝视 <br/> * @param itemList */ public void doDecorate