黑马程序员技术交流社区
标题:
泛型的作用及其意义
[打印本页]
作者:
陈福军
时间:
2013-10-26 22:26
标题:
泛型的作用及其意义
本帖最后由 陈福军 于 2013-10-30 21:29 编辑
最近写作业用的泛型,不知道到底为啥用,求大神解释一下,谢谢
作者:
黑马小子
时间:
2013-10-26 22:36
泛型:通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的复用。
例子代码:
class Program
{
static void Main(string[] args)
{
int obj = 2;
Test<int> test = new Test<int>(obj);
Console.WriteLine("int:" + test.obj);
string obj2 = "hello world";
Test<string> test1 = new Test<string>(obj2);
Console.WriteLine("String:" + test1.obj);
Console.Read();
}
}
class Test<T>
{
public T obj;
public Test(T obj)
{
this.obj = obj;
}
}
输出结果是:
int:2
String:hello world
程序分析:
1、 Test是一个泛型类。T是要实例化的范型类型。如果T被实例化为int型,那么成员变量obj就是int型的,如果T被实例化为string型,那么obj就是string类型的。
2、 根据不同的类型,上面的程序显示出不同的值。
作者:
张小康
时间:
2013-10-26 23:12
我现在学到的是泛型集合(泛型集合指的就是只能存储特定类型的集合),我就说一下为什么要用泛型,
例:有一个数组{1,2,3,4,5,6,7,8,9},放在集合里,求最大值、最小值、和、平均数;
不用泛型集合
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
ArrayList list = new ArrayList();
list.AddRange(numbers);
int max = (int)list[0];//用来存放最大值
int min = (int)list[0];//用来存放最小值
int sum = 0;
for (int i = 0; i < list.Count; i++)
{
if ((int)list[i] > max)//当前成员大于max
{
max = (int)list[i];
}
if ((int)list[i] < min)//当前成员小于min
{
min = (int)list[i];
}
sum += (int)list[i];
}
Console.WriteLine("最大值是{0},最小值是{1},总和是{2},平均值是{3}", max, min, sum, sum / list.Count);
复制代码
使用泛型
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List<int> list = new List<int>();
list.AddRange(numbers);
int max = list[0];//用来存放最大值
int min = list[0];//用来存放最小值
int sum = 0;
for (int i = 0; i < list.Count; i++)
{
if (list[i] > max)//当前成员大于max
{
max = list[i];
}
if (list[i] < min)//当前成员小于min
{
min = list[i];
}
sum +=list[i];
}
Console.WriteLine("最大值是{0},最小值是{1},总和是{2},平均值是{3}", max, min, sum, sum / list.Count);
复制代码
两段代码的区别是,第二个使用了泛型集合,这样,从集合中取值的时候,不需要,转换取值的类型,因为在泛型集合中,已经限定了添加的类型,这样也就不需要装箱和拆箱,提高了程序运行的效率。
作者:
李洋
时间:
2013-10-27 09:30
泛型:是一种能表达能够表达更广泛数据的类型,注意咯,泛型变量的值是一种类型,而非类型取值范围内的值。
泛型机制是一种特殊的类型机制,有两方面的功能:
1. 通用型功能:泛型机制提供一种特殊的带参数描述方式(特殊在于:以类型为参数) 比如上面:T是形式参数,T可以取值Integer、String这些类型。
2. 类型检查功能:说到泛型的类型检查,这就是为什么上面那个例子可以用泛型而不能用Object的原因了。借助编译器当你传入的数据a为整形数据而b为字符串数据时编译阶段会报错。
注意:泛型的检查是在编译阶段的,对于这点要谨记。在java的泛型机制中,必须在编译阶段确知填入的具体类型,不支持在程序的运行阶段传入类型参数。普通的参数都是在运行时传入的,但泛型参数必须在编译时确定。
泛型的申明
class 类名 <类型参数列表>{类体}
如: class A<T1, T2> {T1 a; T2 b;} // 在类体中,你把T1,T2当做已知类来使用就好了
泛型的具体化
类名 <具体类型列表> 变量=new 类名<具体类型列表>{构造函数的参数列表} // 注意:具体类型必须是引用型类型
如:A<Integer, String> x=new A<Integer, String>();
泛型参数可以出现在什么地方
泛型参数可以出现在类、接口、成员方法、内嵌类、内嵌接口中
值得注意的是:泛型方法不仅可以出现在泛型类中,也可以出现在普通类中。不过,当泛型方法出现在普通类中时,记得要在泛型方法中申明泛型参数。 如:
<T> void function(T a){……}
泛型约束和泛型通配符
泛型约束:<T extends BoundingType> // BoundingType 可以是类,也可以是接口;可以有多个BoundingType,用&隔开;但只能有一个类并必须放在第一位置
表示 T必须是BoundingType的子类型(具体化时确定了),或者是实现了BoundingType这个接口的类型
如:<T extends Number> // 要求T的值是Number的子类,且不能是Number类型
<T extends Comparable> // 要求T的值(类型)是个实现了Comparable接口的类
泛型中的通配符:<? extends T> // T即可以是类也可以是接口,把?理解为类型参数,T是类型的上界;?必须是T的子类
来比较一下: LinkList<Number> // 以具体化,说明LinkList类中的数据必须是Number类型或者Number的子类型
LinList<T extends Number> // T标识的是一种确定的类型参数,需要要具体化的
LinkList<? extends Number> // ?标识的是一种不确定的类型参数,不要具体化的
来验证一下LinkList<Number>的LinkList类中可以是Number的子类型:
[java] view plaincopy
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TestClass<Number> test=new TestClass<Number>(3);
TestClass<Number> test1=new TestClass<Number>(2.33);
//TestClass<Number> test=new TestClass<Integer>(3); 注意:编译报错
System.out.println(test.getData());
System.out.println(test1.getData());
}
}
class TestClass<T>{
private T date;
TestClass(T data){
this.date=data;
}
public void setData(T data){
this.date=data;
}
public T getData(){
return this.date;
}
}
输出:
3
2.33
这样看起来感觉后面两个差不多,其实是非常有区别的,举个列子老看下:
[java] view plaincopy
// 一个链表,节点中的数据必须是可比较的
import java.util.Scanner;
public class Ch_11_3 {
/**
* @param args
*/
public static void main(String[] args) {
// 整形数据链表
System.out.println("创建整数链表,以-1结尾:");
Scanner in=new Scanner(System.in);
LinkList<Integer> int_list=new LinkList<Integer>();
int x=in.nextInt();
while(x!=-1){
int_list.addNode(x);
x=in.nextInt();
}
int_list.printList();
System.out.println();
// String类型数据链表
System.out.println("输入一组String,以空格为分隔符:");
LinkList<String> string_list=new LinkList<String>();
Scanner in_2=new Scanner(System.in);
String str=in_2.nextLine();
String[] str_array=str.split(" ");
for(String s : str_array){
string_list.addNode(s);
}
string_list.printList();
}
}
class LinkList<T extends Comparable>{//Comparable 是个接口 <T extends BoundingType> Bounding可以是个类也可以是个接口
// 定义节点类
class Node{
private T data; //节点存储的数据
private Node next; //指向后一节点的指针
public Node(T x){ // 构造函数
this.data=x;
}
public Node getNext(){ //获取节点的后一个节点
return this.next;
}
public void setNext(Node p){ //设置指针的指向元素
this.next=p;
}
public T getData(){ //获取节点元素
return this.data;
}
public void setData(T d){ //设置节点元素
this.data=d;
}
}
private Node head,tail; // 头指针和尾指针
public LinkList(){
head=tail=null;
}
public boolean isEmpty(){ //判断是否为空链表
return head==null;
}
public Node getHead(){ //获取表头
return head;
}
private T max(T a, T b){ //比较两个节点的元素大小
return (a.compareTo(b)>0)?a:b;
}
public T getMaxValue(){ //获取链表中的最大值
if(isEmpty()){
return null;
}
T max_value=this.head.getData();
Node p=this.head.getNext();
while(p!=null){
max_value=max(p.getData(),max_value);
p=p.next;
}
return max_value;
}
public void printList(){
Node p=head;
while(p!=null){
System.out.print(p.getData()+"==");
p=p.getNext();
}
}
public void addNode(T x){
Node p=new Node(x);
if(isEmpty()){
head=tail=p;
}
else{
tail.setNext(p);
tail=p;
}
}
}
作者:
马晓平
时间:
2013-10-28 21:23
泛型:JDK 1.5版本以后出现的心特性,用于解决安全问题,是一个类型安全机制。
好处
1,将运行时期出现的问题ClassCastException,转移到了编译时期
方便程序员解决问题,让运行时期问题减少,安全。
2,避免了强制转换的麻烦
泛型的格式:通过<>来定义要操作的引用数据类型
在使用java提供的对象时,什么时候写泛型呢?
通常在集合框架中很常见
只要加到<>就要定义泛型
其实<>就是用来接收类型的
当使用集合时,将集合中要存储的的数据类型作为参数传递到<>中即可
//泛型类
class Utils<QQ>
{
private QQ q;
public void setObject(QQ q)
{
this.q=q;
}
public QQ getObject()
{
return q;
}
}
class GenericDemo2
{
public static void main(String[] args)
{
Utils<Worker> u=new Utils<Worker>();
u.setObject(new Worker());
Worker w=u.getObject();
}
}
这就是一个泛型的简单例子希望能帮到你
作者:
茹化肖
时间:
2013-10-28 22:07
使用泛型,第一可以节省时间和空间,防止代码的臃肿,提高效率,因为不用再写很多不同类型的重载。在定义的时候不用写具体的数据类型,只在使用的时候确定数据类型即可。
第二呢,就是在你不确定你的参数会是什么类型的时候使用。
第三 ,也是我们最常用的。就是用泛型集合。List<T>. 我们用泛型集合 可以在使用的时候 省去装箱与拆箱的操作,避免了各种数据类型之间转换容易出错。而且,泛型也是强类型哦。
作者:
追溯客
时间:
2013-10-29 07:43
问题解决请将分类设为"已解决".黑马有你更精彩
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2