Java-泛型

Java-泛型

    • 一、泛型相关概念
    • 二、含有泛型的类
    • 三、含有泛型的方法
    • 四、含有泛型的接口
      • 1.在进行实现类的创建时,指定接口的泛型
      • 2.在进行实现类的创建时,给实现类也加上泛型
    • 五、泛型通配符
      • 1.泛型通配符
      • 2.泛型通配符高级使用

一、泛型相关概念

泛型:规定存储在集合中的所有元素的统一数据类型,尖括号<E>代表泛型,E代表
     集合中所有元素的数据类型(E只是个代号,可以根据需要随意起名,例如<M>
     ,<T>)
 注意:
     1.泛型只能是引用数据类型,不能是基本数据类型,如果想要使用基本类型,
       需要使用基本类型的包装类
     2.泛型可以理解为是一个变量,用于接收数据类型
为什么要使用泛型:
见下图
使用泛型和不使用泛型的区别
1.不使用泛型
       好处:集合中可以存储任意数据类型对象,它们会被默认提升到Object类型
       坏处:
         1.当取出一个指定数据类型的对象,进行其特有的操作时,必须进行类型转换,
         2.不安全,编译期(写代码时)可能不会出错,但运行期(代码运行)可能会报错。
2.使用泛型:
       好处:
         1.集合中存储的是同一数据类型数据,避免了类型转换。
         2.把运行期异常,转换到编译期异常,编译不出错,运行就不出错
       坏处:只能存储指定类型数据

Java-泛型_第1张图片

public class GenericDemo01 {
     
	public static void main(String[] args) {
     
		//创建一个不使用泛型的集合对象
		Collection col1 = new ArrayList();
		//可以存储多类型数据
		col1.add(1);//int
		col1.add("abcd");//字符串
		col1.add(true);//布尔值
		System.out.println(col1);//输出结果:[1, abcd, true]
		
		//使用迭代器进行集合遍历
		Iterator it1 = col1.iterator();
		while(it1.hasNext()){
     
			Object obj = it1.next();
			System.out.print(obj+" ");//输出集合1 abcd true 
			
			//当取出一个String类的对象,进行其特有的操作length()时,Object obj = "abcd"为多态必须进行类型转换,
			String str = (String)obj;
			//出现异常:java.lang.Integer cannot be cast to java.lang.String,String类型数据可以进行转换,
			//但是int类型数据不能进行转换为String
			System.out.println(str.length());
			  	
			
		}
		
	        //创建一个使用泛型的集合对象
				Collection<String> col2 = new ArrayList<>();
				col2.add("abc");
				//col2.add("1");//编译报错:不能直接将int类型数据存进去,避免出现不使用泛型时出现的运行异常情况
				System.out.println(col2);//输出结果:[abc]
				
				//使用迭代器进行集合遍历
				Iterator<String> it2 = col2.iterator();//迭代器泛型和集合保持一致
				while(it2.hasNext()){
     
					String str = it2.next();//不需要进行类型转换,因为存储的数据类型一致
			        //System.out.print(str+" ");//输出结果:abc
			        //可以直接使用String类的特有方法,而且不会报错,因为进行添加数据时,只能添加String类型数据
			        //如果不是,编译直接报错
			        System.out.println(str.length());//输出结果:3
				}
				
		
	}

}

二、含有泛型的类

 使用泛型定义一个类:当一个类不确定将要使用什么数据类型,可以使用泛型
 定义格式:修饰符 class 类名称<E>{
     
                        内容
     }
     
 使用格式:
      类名<E>  对象名 = new 类名称<>();
public class GenericDemo02 {
     
	public static void main(String[] args) {
     
		//定义一个泛型类的对象,可以根据需要进行不同类型的定义
		//使用String数据类型
		GenericDemo<String> name = new GenericDemo<>();
		name.setStuName("王小明");
		name.setAge(10);
//		name.setAge("str");//报错:基本数据类型,什么类型放什么类型数据
		System.out.println(name.getStuName());//输出结果:王小明
		
		//使用Integer数据类型
		GenericDemo<Integer> name1 = new GenericDemo<>();
		name1.setStuName(1);
		name.setAge(10);
		System.out.println(name1.getStuName());//输出结果:1
	}

}

//使用泛型定义一个类,本质上和之前定义类没什么区别,只是在类名名后加上了泛型,变量定义有些不同,
//当然也可以定义基本类型数据,而且基本数据类型的使用是不变的,什么类型仍然只能赋什么类型的值,int类型的只能赋整型的值
//不会因类的泛型改变而改变,只用被E修饰的变量,才会随着泛型的变换而变换
class GenericDemo<E>{
     
	private E stuName;
	private int age;

	public int getAge() {
     
		return age;
	}

	public void setAge(int age) {
     
		this.age = age;
	}

	public E getStuName() {
     
		return stuName;
	}

	public void setStuName(E stuName) {
     
		this.stuName = stuName;
	}
	
	
}

三、含有泛型的方法

定义含有泛型的方法
定义格式: 修饰符 <M> 返回值类型 方法名(参数列表(使用泛型)){
     //<>里的名称                                             可以自由定义
                       方法体;
                      } 
使用格式:
      在调用方法的时候进行指定类型,参数传递的是什么类型,
      泛型就是什么类型
public class GenericDemo03 {
     
	public static void main(String[] args) {
     
		//创建一个对象
		GenericDemo1 demo=new GenericDemo1();
		//调用方法时指定数据类型,可以指定任意引用数据类型,传递什么类型,泛型就是什么类型
		demo.method(1);//输出结果:1
		demo.method("字符串");//输出结果:字符串
		demo.method(true);//输出结果:true
		
		//使用类名.静态方法名来使用静态方法
		GenericDemo1.method2(1);//输出结果:1
		GenericDemo1.method2("字符串");//输出结果:字符串
		GenericDemo1.method2(true);//输出结果:true
		
	}
	
	


}
class GenericDemo1{
     
	// 在调用方法的时候进行指定类型,参数传递的是什么类型,泛型就是什么类型
	//普通方法
	public <M> void  method(M m){
     
		System.out.println(m);
		
	}
	
	//静态方法,和普通方法一样
	public static <T> void method2(T t){
     
		System.out.println(t);
	}
}

四、含有泛型的接口

带有泛型的接口:
 定义格式:
      public interface 接口名<I>{
     
                   方法定义
      }
使用格式:
   1.在进行实现类的创建时,指定接口的泛型
     格式:修饰符 class 实现类名称 implements 接口名<数据类型>{
     }
      例:public interface Iterator<I>{
     //Iterator接口
         I  next();//获取元素方法
      }
      public class Scanner implements Iterator<String>{
     } //Scanner类实现了Iterator接口,并指定泛型为String,
                                                                                                                     所以Scanner中的next方法默认返回的是字符串类型
   2.在进行实现类的创建时,给实现类也加上泛型,但是需要和接口保持一致
        格式:修饰符 class 实现类名称<I> implements 接口名<I>{
     }

1.在进行实现类的创建时,指定接口的泛型

//接口
public interface Generic<T> {
     
	public void method(T t);

}

//接口的实现类
public class GenericDemo04 implements Generic<String>{
     //创建是实现类时,指定接口泛型

	@Override
	public void method(String t) {
     //接口泛型指定,方法参数类型和接口保持一致
		// TODO Auto-generated method stub
		System.out.println(t);
	}

}

public class GenericDemo05 {
     
	public static void main(String[] args) {
     
		//创建一个接口的实现类对象,进行方法调用即可
		GenericDemo04 g = new GenericDemo04();
		g.method("字符串");//输出结果:字符串
	}

}

2.在进行实现类的创建时,给实现类也加上泛型

//接口
public interface Generic<T> {
     
	public void method(T t);

}

//实现类
//格式:修饰符 class 实现类名称 implements 接口名{}
public class GenericDemo06<T> implements Generic<T> {
     

	@Override
	public void method(T t) {
     
		// TODO Auto-generated method stub
		System.out.println(t);
	}

}

public class GenericDemo07 {
     
	public static void main(String[] args) {
     
		//创建对象时指定泛型
		GenericDemo06<String> g = new GenericDemo06<>();
		g.method("字符串");//输出结果:字符串
		
		GenericDemo06<Integer> i = new GenericDemo06<>();
		i.method(2);//输出结果:2
	}

}

五、泛型通配符

1.泛型通配符

泛型通配符:
在不知道泛型类和泛型接口中传递的是什么数据,可以使用泛型通配符<?>,?可以表示任意数据类型
一旦使用泛型通配符,只能使用Object类中的共性方法,不能使用集合元素的特有方法

泛型通配符只能接收数据,不能向集合中存储数据,

与之前的区别:
            之前的泛型必须先定义才能使用,泛型通配符已经存在,可以直接
            使用
               
使用方式
    1.不能创建对象使用,
    2.只能作为方法参数使用
   
注意:泛型没有继承的概念
     ArrayList<Object> obj = new ArrayList<String>();//错误写法
    public static void method(Collection<?> al){
     //可以遍历不同类型集合的
    	//创建一个迭代器对象
    	Iterator it1 =al.iterator();
    	while(it1.hasNext()){
     
    		Object obj = it1.next();
    		System.out.print(obj+" ");
    	}
    
	
	
//   public static void method(Collection il){//此方法不能遍历col2
//    	    	//创建一个迭代器对象
//    	    	Iterator it1 =il.iterator();
//    	    	while(it1.hasNext()){
     
//    	    		Object i1 = it1.next();
//    	    		System.out.print(i1+" ");
//    	    	}
	
	
//	
//	  public static void method(Collection al){//此方法不能遍历col1和col2,
//	    	//创建一个迭代器对象
//	    	Iterator it1 =al.iterator();
//	    	while(it1.hasNext()){
     
//	    		Object obj = it1.next();
//	    		System.out.print(obj+" ");
//	    	}
    }
}

 
  

2.泛型通配符高级使用

 通配符的高级使用--受限泛型  (了解即可)
 泛型上限限定:? extends E  使用的泛型只能是E类型的子类或者本身
 泛型下限限定:? super E    使用的泛型只能是E类型的父类或者本身
public class GenericDemo09 {
     
	public static void main(String[] args) {
     
				Collection<Integer>  col1  = new ArrayList<>();
				Collection<String> col2 = new ArrayList<>();
				Collection<Number> col3 = new ArrayList<>();
				Collection<Object> col4 = new ArrayList<>();
				
//			

				
	}
	//Integer继承了Number.Number继承了Object
	//String继承了Object
	
	
  //泛型上限限定,此时的?必须是Number的子类或者本身
	public static void method1(Collection<? extends Number> col){
     }
	//泛型下限限定,此时的?必须是Number的父类或者本身
	public static void method2(Collection<? super Number> col){
     }
}

你可能感兴趣的:(Java,编程语言,java,泛型)