泛型在类、方法、接口中的使用
1.泛型在类中的使用
为什么要在类上使用泛型?
(1).为了让当前的Tool1类可以通过给更多类型的对象传值
(2).不需要再进行类型转换,就可以避免错误发生
//使用泛型前
class Tool{
private Object obj;
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
//使用泛型后
/*
E:代表任意一种引用数据类型,<>中不一定是E,可以使用任意字符
相当于在给类使用泛型
-
使用:在类上确定的泛型可以直接在内部成员上使用
*/
class Tool1<E>{
private E obj;public E getObj() {
return obj;
}public void setObj(E obj) {
this.obj = obj;
}
}
2.泛型在方法中的使用
class Test<E e>{
//1.方法上的泛型与类上的泛型保持一致,一旦类上的泛型确定了,方法上的就确定了
public E show(E e){
return e;
}
//2.方法上使用自己的泛型
注意:泛型在使用之前一定要进行声明
声明的方法:在方法的最前面使用<泛型类型>
作用:让方法的内部与方法的泛型保持一致
public <F> void play(F f){
ArrayList<F> list = new ArrayList<>();
}
//3.静态方法使用泛型
//类上的泛型无法在静态方法上使用,静态方法必须自己定义
public static <W> void song(W w){
}
}
总结:泛型在方法中的使用,只有与类保持一致的类型是,不需要重新声明,方法中使用自己的泛型以及静态方法都需要重新声明泛型类型
3.泛型在接口中使用
interface Inter<E>{
public void shoe(E e);
}
//相应的子类使用泛型的方式
//1.接口有泛型,子类没有遵守对应的泛型
两种情况:
a.对于重写的接口方法:泛型的和接口的保持一致,即方法的泛型也要给一个具体的类型
b.对于自己特有的方法,可以与接口一致,也可以自己定义泛型
class Pig implements Inter<String>{
第一种情况:
public void show(String e){
}
第二种情况:
public <F>void play(F f){
}
}
2.接口有泛型,子类遵守对应的泛型
类上的泛型确定了,接口上的就确定了,重写方法上也确定了
class Dog<E> implements Inter<E>{
public void show(E e){
}
}
总结:接口上的泛型,在子类实现的时候,如果接口后面接着一个具体的类型(比方说:String),就不需要在类后面声明了,如果接口后面是E、F、W等抽象的类型,即使类型和接口中的一模一样,也要声明,就需要在类后面声明:<E>、<F>、<W>
限制上限:<? extends E>:限制的是整个<>可以取的泛型的类型上限是E,<>中可以取的泛型是E类以及E的子类
限制下限:<? super E>:限制的是整个<>可以取的泛型的类型下限是E,<>中可以取的泛型是E 类及E的父类
collection:直接存储的元素(值)
Map:本身是一个接口,存储的是键值对,Map中一个元素是一个键值对(key:键,value:值),key必须保证唯一,value可以相同
分类:HashMap:底层是哈希表,线程不安全的
TreeMap:底层是二叉树,线程不安全的
//创建一个 Map<键的类型,值的类型>
Map<String,String> map = new Map<>();
//1.增加: V put(K key, V value) 一次增加一份键值对
map.put("01","java");
map.put("02","php");
//因为key是唯一的,如果给同一个key重复赋值,后面的值会将前面的覆盖掉,并将覆盖的值返回,如果第一次使用key,返回null
String value3 = map.put("01","ios");//value是java
//void putAll(map<? extends K,? extends V> map)
Map<String,String> map1=new HashMap>?();
map1.put("03","html");
map1.put("04","python");
map.putAll(map1);
2.删除
//V remove (Object key) 根据key删除元素,并将删除的元素返回
map.remove("01")//删除只需要删除key就可以删除整个键值对
//void clear() 删除全部!=null,而是一个空的集合
3.获取
//V get(Object key) 根据key获取一个值
map.get("02")
//int size() 返回键值对的个数
map.size();
//遍历1:Set<K> KeySet
//遍历2:Set<map.entry<K,V>> entrySet()
4.一些常用的判断
//boolean isEmpty() 判断是否为空
//boolean containsKey(Object key) 判断是否包含当前的Key
//boolean containsValue(Object value) 判断是否半寒当前的value
//遍历1:Set<key> KeySet()
//原理:得到所有的key存放在set中,利用set的迭代器遍历得到key
//遍历2:Set<Map.entry<K,V>> entrySet()
//原理:得到的是每个键值对对应的映射关系类型的对那个(实体/entry对象),存在set中,利用set的迭代器遍历得到entry,在利用entry获取具体的value
public static void main(String[] args){
Map<String,String> map = new Map<>();
map.put("01","java");
map.put("02","php");
map.put("03","html");
map.put("04","python");
map.put("00","ok");
}
//1.使用Set<K> keyset()//这里是Map的引用来调用keyset
Set<String> set1 = map.keyset();
//获取迭代器
Iterator<String> iterator = set1.iterator;
while(iterator.hasnext()){
String string = iterator.next();
System.out.println("key:"+String+" value:"+map.get(string));
}
//使用Set<Map.Entry<K,V>> entrySet()//Entry是Map中一个静态接口
Set<Map.Entry<String,String>> set2 = map.entrySet();
//获取迭代器
Iteraror<Map.Entry<String,String>> iterator = set2.iterator();
while(iterator.hasnet()){
Map.Entry<String,String> entry = iterator.next();
System.out.println("key:"+entry.getkey()+" value:"+entry.getvalue());
}
总结:两种迭代器,一种是通过将key存到Set中,通过keySet方法存入,一个是将键值对的映射即Map.Entry存到Set中,即通过entrySet方法中,然后通过Set中遍历进行取值