【Java15】泛型


1.泛型

在这里插入图片描述
如下不用泛型。
在这里插入图片描述
如下没有泛型存在安全问题,泛型就和overwrite注解一样,要不要无所谓,要就检查。
在这里插入图片描述
在这里插入图片描述

/*
*   1. 为什么要使用泛型?
*       1. 一般的需求, 一个集合都是用来同一种类型的数据 , 早期是没有泛型的, 意味着集合可以存任意引用类型
*       2. 这样就带来一个问题: 但凡需要用来子类特有方法, 集合类型为Object,都需要向下转型(强转)
*           -> 风险: 类型转换异常 (运行的时候)
*       3. 泛型: 给集合设置泛型, 那么这个集合就会在编译时候发现运行时期才发现的问题
*           先编译 后运行。泛型: 安全预警机制, 不是强制使用, 一般都会用
*
*   2. java里的泛型 是 伪泛型:java泛型只存在编译时期(泛型擦除), 不存在运行时期
*/

在这里插入图片描述
如下ArrayList < Object> 类型是ArrayList < String>的父类吗?不是,因为放动物(Object)笼子不能说是放狗(String)笼子的爸爸,本质都是笼子(ArrayList),但可以说动物是狗的父类。

package com.itheima06.generic;
import java.util.ArrayList;

public class GenericClassDemo {
    
    
    public static void main(String[] args) {
    
    
        ArrayList<Integer> list = new ArrayList<>();
        list.add(100); 
        Integer integer = list.get(0); //0为int index        
		
		//如上add,get只能是Integer,原因如下:
        //对mc来说, 在创建对象时, T=String
        MyClass<String> mc = new MyClass<>();
        mc.add("abc");    
            
		//对mc2来说, 在创建对象时, T=Integer
        MyClass<Integer> mc2 = new MyClass<>();
        mc2.add(1);
    }
}
/*
*   泛型类: 1. class 类名<泛型变量>{ }
*           泛型变量 一般为单个大写字母
*         2. 泛型T 变量 , 只能赋值引用类型 String,Integer...
*         3. 创建对象的时候,对T 进行赋值
*         4. 某个泛型类对象 T赋值为String,那么这个对象中所有的T=String
*/    
class MyClass<T>{
    
     
    public void add(T str){
    
     //str随便写 
    }
}
package com.itheima06.generic;
import java.util.ArrayList;
import java.util.Properties;
/*
*   泛型接口: interface 接口名<泛型变量>{  }
*   类实现泛型接口:1. 继续向下传递泛型  2. 直接对泛型进行赋值,不再向下传递
*/
public class GenericInterfaceDemo {
    
    
    public static void main(String[] args) {
    
    
        new Properties(); //ctrl+左键进去看源码 //Properties类是Properties文件和程序的中间桥梁,不论是从properties文件读取信息还是写入信息到properties文件都要经由Properties类
    }
}
interface MyInter<Q>{
    
    
    void add(Q q);
}
class MyClass01<Q> implements MyInter<Q>{
    
     //继续向下传递泛型 //eg: ArrayList类
    @Override
    public void add(Q q) {
    
     //一个类实现接口必须重新给方法
    }
}
class MyClass02 implements MyInter<String>{
    
     //Q赋值为String //eg: Property类
    @Override
    public void add(String s) {
    
    
    }
}
package com.itheima06.generic;
import java.util.ArrayList;
/*
*   泛型方法: 修饰符  <泛型变量> 返回值 方法名(参数列表){
*             }
*            1. 泛型变量在调用此方法的时候进行赋值
*            2. 泛型变量只可本方法内部
*   需求: 请你设计一个方法 既能接收list1,又能接收list2
*/
public class GenericMethodDemo {
    
    
    public static void main(String[] args) {
    
    
        ArrayList<String> list1 = new ArrayList<>();
        ArrayList<Integer> list2 = new ArrayList<>();
        MyClass03.method00(list1); // P = String
        MyClass03.method00(list2); // P = Integer
    }
}
class MyClass03{
    
    
    public static <P>void method00(ArrayList<P> list){
    
     //写成ArrayList<Object> list不行,蓝子间没继承关系。//ArrayList<Object>类型不是ArrayList<Integer>类型的父类,运行擦除泛型可以通过但在编译一开始就不能通过
    }
}

2.泛型通配符

在这里插入图片描述
如上由于bigList这行导致Fu fu报红,不应该为Fu fu报红,应该改为将addAll(list);改为报红,所以上面的泛型方法不行,用泛型通配符
在这里插入图片描述

package com.itheima06.generic;
import java.util.ArrayList;
/*
*   泛型通配符 : ?(表示一个范围)
*       1. ? extends Fu : Fu及其子类 (上限)
*       2. ? super  XX : XX及其父类 (下限)
*/
public class GenericSymbolDemo {
    
    
    public static void main(String[] args) {
    
    
        ArrayList<Fu> fuList = new ArrayList<>();
        ArrayList<Zi> ziList = new ArrayList<>();
        ArrayList<Sun> sunList = new ArrayList<>();
        ArrayList<Object> objList = new ArrayList<>();
        addAll(fuList);
        addAll(ziList);
        addAll(sunList);
       //addAll(objList); //编译不通过,放不进
    }
    /*
    *   方法: 内部有个内部有个bigList, 想要把参数(集合)中的所有元素都吸纳
    *           内部有个bigList  :  ArrayList<Fu> : 吸纳 : Fu 及其子类 的元素类型集合
    */
    private static void addAll(ArrayList<? extends Fu> list) {
    
    
        ArrayList<Fu> bigList = new ArrayList<>();
//        bigList.add(new Fu());
//        bigList.add(new Zi()); //向上转型
//        bigList.add(new Sun()); //向上转型
        for (Fu fu : list) {
    
    
            bigList.add(fu);
        }
    }
}
class Fu{
    
    
}
class Zi extends Fu{
    
    
}
class Sun extends Zi{
    
    
}

3.练习

public class TestGeneric {
    
    	
	@Test
	public void test1(){
    
    		
		ArrayList list = new ArrayList();  //存本组学员的姓名,String对象
		list.add("张三");
		list.add("李四");
		list.add("王五");
		list.add(1);		
		for (Object object : list) {
    
     //使用时,不知道我这里面是String类型,统统按照Object
			//每次使用元素时,可能需要强转,很麻烦,好比每次打开瓶子,你需要闻一下
			String name = (String) object;//强转有风险
			System.out.println("名字的长度:" + name.length());
		}
	}
}
package com.atguigu.test02;
import java.util.ArrayList;
import org.junit.Test;
// 泛型的好处:(1)安全(2)避免类型转换
public class TestGood {
    
    
	@Test
	public void test1(){
    
    
		ArrayList<String> list = new ArrayList<String>();
		list.add("张三");
		list.add("李四");
		list.add("王五");
//		list.add(1);//编译报错,因为我告诉ArrayList,我的元素类型是String,所以Integer对象进不去		
		//此时不需要用Object处理了,因为它知道里面的元素是String
		for (String name : list) {
    
    
			System.out.println("名字的字数:" +name.length());
		}
	}
}
package com.atguigu.test03;
import java.util.ArrayList;
import java.util.Iterator;
/*
 * 把本组学员的姓名,存储到ArrayList集合中,并且指定泛型,并且要使用foreach和Iterator分别迭代,也要正确指定泛型
 */
public class TestExer1 {
    
    
	public static void main(String[] args) {
    
    		
		ArrayList<String> list = new ArrayList<String>(); //姓名,泛型指定为String	
		list.add("杨洪强");
		list.add("苏海波");
		list.add("甄玉禄");
		
		System.out.println("foreach迭代");
		for (String name : list) {
    
    
			System.out.println(name);
		}
		
		System.out.println("Iterator迭代");		
		//Iterator<E>这个E代表你要迭代的集合的元素类型
		Iterator<String> iterator = list.iterator();
		while(iterator.hasNext()){
    
    
			String name = iterator.next();
			System.out.println(name);
		}
	}
}

在这里插入图片描述

package com.atguigu.test03;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
/*
 * 把本组学员的组长姓名作为key,组员的姓名作为value,多个组员用ArrayList装起来,
放到HashMap中,正确指定泛型,并且遍历。当如果出现泛型的嵌套,那么从外到内分析
 */
public class TestExer2 {
    
    
	public static void main(String[] args) {
    
    
//HashMap<K,V>:K代表key的类型,V代表value的类型
//组长姓名作为key,说明K是String。组员的姓名作为value,多个组员用ArrayList装起来,说明V是ArrayList类型
//因为ArrayList也是泛型类,ArrayList中装的是组员的姓名,所以是String类型
		HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();		
		ArrayList<String> group1 = new ArrayList<String>();
		group1.add("杨洪强");
		group1.add("苏海波");		
		map.put("杨洪强", group1); //组长:杨洪强
		
		ArrayList<String> group8 = new ArrayList<String>();
		group8.add("崔志恒");
		group8.add("甄玉禄");
		group8.add("杜冠军");		
		map.put("崔志恒", group8); //组长:崔志恒
		
		System.out.println("遍历所有的组长:");
		Set<String> keySet = map.keySet();
		for (String zuZhang : keySet) {
    
    
			System.out.println(zuZhang);
		}
		
		System.out.println("遍历所有的学员:");
		Collection<ArrayList<String>> values = map.values();
		for (ArrayList<String> group : values) {
    
    
			System.out.println(group);
		}
		
		System.out.println("遍历每一组的情况:");
		Set<Entry<String, ArrayList<String>>> entrySet = map.entrySet();
		for (Entry<String, ArrayList<String>> entry : entrySet) {
    
    
			System.out.println(entry);
		}
	}
}

在这里插入图片描述
B站/知乎/微信公众号:码农编程录
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43435675/article/details/112621130