黑马程序员-- 高级网络编程 什么是泛型?泛型的定义?泛型如何使用?为什么要使用泛型?

 

泛型: 1.5新特性。 解决安全问题,是一个安全机制!
可以指定容器 里要装入的是什么样的数据类型。

可以修饰类,可以修饰方法,

什么是泛型?
如何使用泛型?
为什么要使用泛型?

 

 

 

 

import java.util.*;
public class TestFanXing_1 {
	public static void main(String[] args) {
		ArrayList a1 =new ArrayList();
		a1.add("努力!");
		a1.add("坚持!");
		a1.add("我不二");
		
		//a1.add(4);  编译时间没问题,运行时期出错.
		Iterator it =a1.iterator();
		while(it.hasNext())
		{
			String st =(String)it.next();
			System.out.println(st);
		}
	}
}


 

上面例子没有使用泛型. 容器装的类型不一致,会导致程序不安全.

看下面的例子:

使用了泛型, 解决了安全问题,是一个安全机制.

import java.util.*;
public class TestFanXing_1{
	public static void main(String[] args) {
		ArrayList<String> a1 =new ArrayList<String>(); //定义一个数组容器 里面存放Sstring对象
		a1.add("努力!");
		a1.add("坚持!");
		a1.add("我不二");
		
		Iterator<String> it =a1.iterator(); //构造一个迭代器 取出集合中的元素
		while(it.hasNext())  //迭代器中是否有元素  
		{
			String st =it.next();  //返回迭代的下一个元素
			System.out.println(st+":"+st.length());  //输出元素 以及元素的长度
		}

	}

}

 

 

如何自定义泛型类?
自己定义的类 如何使用泛型?在什么时候使用泛型?
如果有很多类 需要相同的数据,后来的类也需要相同的这些数据,那边就用一个泛型类来设计。提高代码的复用性。
在类名字后面加上 <引用数据类型>  不能是基本数据类型。
注意:在使用泛型类的时候,由类指定要new什么类型的对象
例如A泛型类 要new一个String类型对象  .要这么写: A<String> aa =new A<String>();

class ChenLiHong
{
}
class LvJun
{
}
 
class Happy<YY>  //泛型类
{
	private YY yy;
	public void setYY(YY yy)
	{
		this.yy=yy;
	}
	public YY getYY()
	{
		return yy;
	}
}

/*  
class Happy  普通类
{
	private Object obj;
	public void setObject(Object obj)
	{
		this.obj=obj;
	}
	public Object getObject()
	{
		return obj;
	}
}
*/
class TestRead
{
	public static void main(String[] args)
	{
		Happy<ChenLiHong> ha =new Happy<ChenLiHong>();
		 
		/*
		Happy ha =new Happy();
		定义的类没有加泛型  编译没有问题   运行出错会出现类型转换异常
		ha.setObject(new LvJun()); //编译没有问题,因为参数是Obj类型 
		ChenLiHong  clh =(ChenLiHong)ha.getObject();//运行出错,类型转换异常,设置的是LVJUN,得到的是CHENLIHONG
		
		定义的类 没有加泛型,以前都是客观的,设置什么对象,得到的就点是什么对象。 而且必须强转类型
		ha.setObject(new ChenLiHong());     //正确
		ChenLiHong  clh =(ChenLiHong)ha.getObject();  //正确
		*/
		
		 
		//定义的类加了泛型 ,也就是由类 来指定要操作的什么样的类型对象。
		//ha.setYY(new LvJun());  翻译时期就会出错,提高了代码安全性。
		ha.setYY(new ChenLiHong());
		ChenLiHong clh =(ChenLiHong)ha.getYY();
	}
}


 

泛型定义在接口上:

两种方法: 不常用,但要知道.

语法格式:
  接口泛型类: interface Inter<T>  
				{
					void show(T t);
				}
				//子类在实现泛型类的时候直接定义String类型
   第一种实现: class A implements Inter<String>  
				{
					public void show(T t)
					{
						System.out.println("show :"+t);
					}
				}
				
				构造类: A<String> aa =new A<String>();
						aa.show("成功!");

				//子类在实现泛型类的时候 A类不确定什么类型 实现的Inter也不确定什么类型
    第二种实现:class A<T > implements Intre<T>  
				{
					public void show(T t)
					{
						System.out.println("show :"+t);
					}
				} 
				构造类: A<Integer> aa =new A<Integer>();
					aa.show(4);

泛型定义在方法上: 提高代码的复用性

1:一个A类 内部 有个方法被定义泛型, 那边这个方法只属于本身.

2:一个A类被定义泛型,当A类被new对象的时候,就直接规定是什么引用数据类型.
   //如果A类被定义泛型,调用自己内部的普通方法,那么方法随着A类对象的类型走.
   如果A类被定义泛型,调用自己内部的泛型方法,那么A类随着方法类型走.
   如果A类被定义泛型,调用自己内部的静态方法,编译会出错,因为class A<T>  T只有对象的时候才会被明确类型
   如果A类被定义泛型,静态方法又不确定是什么类型,那么在静态方法上加泛型.
例如:

class A<T>
{
	//如果A类被定义泛型,调用自己内部的普通方法,那么方法随着A类对象的类型走.
	public  void show(T tt)
	{
		System.out.println("show : "+tt);
	}

	//如果A类被定义泛型,调用自己内部的泛型方法,那么A类随着方法类型走.
	public <Q> void print(Q qq)
	{
		System.out.println("print :"+qq);
	}
	/*
	public static void meme(T tt)
	{
		System.out.println("meme :"+tt);
	}

	//A.meme("你好"); 编译错,meme是静态方法,类名调用静态方法,而A类上的泛型<T>只有new对象的时候才会被明确类型
	*/

	//如果A类被定义泛型,静态方法又不确定是什么类型,那么在静态方法上加泛型.
	public static<W> void meme(W ww)
	{
		System.out.println("meme :"+ww);
	}

}

class TestRead
{
	public static void main(String[] args)
	{
		A<String> aa =new A<String>();
		aa.show("坚持");
		aa.print("哈哈");
		//aa.print(new A());  //A@de6ced

		A.meme("你好");
	}
}

 

? 通配符 ,也可以理解为占位符  (具备泛型,但是什么类型不确定.)

使用占位符的好处:扩展性强, 弊端:不能使用特有方法.
public static<T> void print(ArrayList<T> ap) T代表具体类型
public static void print(ArrayList<?> ap)    ? 通配符,什么类型不确定

import java.util.*;
class TestRead
{
	public static void main(String[] args)
	{
		ArrayList<String> ay =new ArrayList<String>();
		ay.add("我不抽烟");
		ay.add("我不喝酒");
		ay.add("我不吃饭");

		ArrayList<Integer> ae =new ArrayList<Integer>();
		ae.add(2);
		ae.add(5);
		ae.add(8);
		
		print(ae);
		 
	
	}
	//遍历集合   一个String类型 一个Integer类型   ,
	//遍历集合,要定义2个迭代器比较麻烦,有什么办法呢? 单独设计一个方法
	/*
	public static void print(ArrayList<String> ap) //ArrayList<String> ap =new ArrayList<String>(); 
	{
		Iterator<String> it = ap.iterator();
		while(it.hasNext())
		{
			System.out.println(it.next());
		}
	}

	主函数调用 :  print(ay); //正确.  参数规定String 引用类型
				  print(ae); //错误   ArrayList<String> ap =new ArrayList<Integer>(); 左右两边类型不匹配
	 */


    /*
	public static<T> void print(ArrayList<T> ap) T代表具体类型
	public static void print(ArrayList<?> ap)  //  ?代表不明确类型. ArrayList<String> ap =new ArrayList<String>(); 
	{
		Iterator<?> it = ap.iterator();
		while(it.hasNext())
		{
			System.out.println(it.next());
		}
	}
	主函数调用 :  print(ay); //正确.  参数规定<?>   ? 通配符 ,也可以理解为占位符  (具备泛型,但是什么类型不确定.)
		    print(ae); //正确   参数规定<?>   ? 通配符 ,也可以理解为占位符  (具备泛型,但是什么类型不确定.)
	?和  T的区别:  T代表具体类型  ?代表不明确类型 比如:传的参数是? 占位符,打印元素和长度,编译就会出错,长度是属于具体类型,而?代表是什么类型不确定.
	使用占位符的好处:扩展性强,    弊端:不能使用特有方法.
	*/
}


 

 

 

泛型的限定:

 ? extends E :可以接受E类型或者E的子类型,上限

? super E :可以接受E类型或者E的父类型   下限

/*

  
import java.util.*;
class TestRead
{
	public static void main(String[] args)
	{
		ArrayList<Person> a2 =new ArrayList<Person>();
		a2.add(new Person("小强"));
		a2.add(new Person("小进"));
		a2.add(new Person("向前"));
		print(a2);

		ArrayList<Student> a4 =new ArrayList<Student>();
		a4.add(new Student("小强00"));
		a4.add(new Student("小进00"));
		a4.add(new Student("向前00"));
		print(a4);
	}
	//打印一个类型的范围: 只打印 Person 和Person的子类 别的不管. 这个时候使用泛型限定
	//<? extends Person> 只能打印,或者只能接收Person 和Person的子类
	public static void print(ArrayList<? extends Person> a3) 
	{
		Iterator<? extends Person> it =a3.iterator();
		while(it.hasNext())
		{
			System.out.println(it.next().getName());
		}
	}



	/*
	public static void print(ArrayList<Person> a3)
	{
		Iterator<Person> it =a3.iterator();
		while(it.hasNext())
		{
			System.out.println(it.next().getName());
		}
	}

	主函数: print(a4); //出错,这句话等于ArrayList<Student> a3 =new ArrayList<Person>(); 左右2边要一致.
	
}*/
 /*
class Person
{
	private String name;
	Person(String name)
	{
		this.name=name;
	}
	public String getName()
	{
		return name;
	}
	public String toString()
	{
		return "person:"+name;
	}
}

class Student extends Person
{
	private String name;
	Student(String name)
	{
		super(name);
	}
}

class Worker extends Person
{
	Worker(String name)
	{
		super(name);
	}
}



*/

/*

?  super   E  :可以接受E类型或者E的父类型
例子:  
*/
import java.util.*;
class TestRead
{
	public static void main(String[] args)
	{
		TreeSet<Student> ts =new TreeSet<Student>(new StuComp());

		ts.add(new Student("sss--5555"));
		ts.add(new Student("sss--888"));
		ts.add(new Student("sss--333"));
		ts.add(new Student("sss--444"));

		Iterator<Student> it =ts.iterator();
		while(it.hasNext())
		{
			System.out.println(it.next().getName());
		}

		TreeSet<Worker> ts1 =new TreeSet<Worker>(new StuComp());

		ts1.add(new Worker("fgdfg"));
		ts1.add(new Worker("hdfdh3"));
		ts1.add(new Worker("fhdfh23"));
		ts1.add(new Worker("hfgj555"));

		Iterator<Worker> it1 =ts1.iterator();
		while(it1.hasNext())
		{
			System.out.println(it1.next().getName());
		}
	}
}

/*
class StuComp implements Comparator<Student>
{
	public int compare(Student s1,Student s2)
	{
		return s1.getName().compareTo(s2.getName());
	}
}

class WorkerComp implements Comparator<Worker>
{
	public int compare(Worker s1,Worker s2)
	{
		return s1.getName().compareTo(s2.getName());
	}
}
*/
class StuComp implements Comparator<Person>  // 可以接受E类型或者E的父类型
{
	public int compare(Person p1,Person p2)
	{
		return p2.getName().compareTo(p1.getName());
	}
}


class Person
{
	private String name;
	Person(String name)
	{
		this.name=name;
	}
	public String getName()
	{
		return name;
	}
	public String toString()
	{
		return "person:"+name;
	}
}

class Student extends Person
{
	private String name;
	Student(String name)
	{
		super(name);
	}
}

class Worker extends Person
{
	Worker(String name)
	{
		super(name);
	}
}




 

 

 

 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值