概念:是一个未知的数据类型,是一个参数化类型
使用场景:
在定义类型时,类上有泛型的使用,那么该类就是泛型类
格式:
class 类名<泛型>{ } class person<T>{ private T name; }
注意事项:
如果想要在类中使用泛型,首先需要在类的声明上,声明该泛型符号
如何定义泛型:
如果一个类型定义了泛型,在使用这个类型的时候,可以确定泛型也可以不确定泛型。
如果不确定泛型的话:默认使用Object来接收参数
如果确定了泛型:那么就只能使用确定的类型来接收参数
在确定泛型的时候,泛型前后要一致
可以在一个类中使用多个不同的泛型,使用几种就需要声明几种
在使用类型时,如果类型声明了多个泛型,要么一个都不指定,要么全都指定
**好处:**可以提高类型的扩展性
代码:
public void main(String[] args) { person p = new person(); p.name = 180.2; p.age = "453"; person<String, Integer> p1 = new person<>(); p1.name = "chen"; p1.age = 11; person<Double,Boolean> p2 = new person<>(); p2.name = 18.5; p2.age = true; } class person<T,M>{ T name; M age; }
使用泛型定义的方法
格式:
修饰符 <泛型的声明> 返回值类型 方法名(){ }
注意事项:
public void main(String[] args) { printValue("chen"); printValue(124); //默认转换成Integer类型、只能是引用类型 } //定义了一个静态方法,必须先声明泛型 public static <T> void printValue(T t){ System.out.println(t); }
public class E <L>{ public void main(String[] args) { E e = new E(); e.printValue1(11); } //可以在类上声明 public void printValue1(L l){ System.out.println(l); } //也可以自己声明 public <L> void printValue1(L l){ System.out.println(l); }
public void main(String[] args) { printValue2("chen",22); } public static <P,M> void printValue2(P t,M m){ System.out.println(t); System.out.println(m); }
概述:如果接口中的抽象方法需要使用泛型,也需要先在接口上声明该泛型
注意:
//接口中应用泛型 public interface A <T,M>{ public T get(); public void set(M m); } //实现类实现该接口 public class elemA implements A{ @Override public Object get() { //默认Object类型 return null; } @Override public void set(Object o) { } }
//接口中应用泛型 public interface A <T,M>{ public T get(); public void set(M m); } //实现类实现该接口 public class elemA implements A<String,Integer>{ @Override public String get() { return null; } @Override public void set(Integer integer) { } }
//接口中应用泛型 public interface A <T,M>{ public T get(); public void set(M m); } //实现类实现该接口,泛型不指定,需要在类名后声明 public class elemA <T,M> implements A<T,M>{ @Override public T get() { return null; } @Override public void set(M m) { } }
概述:学习的集合是支持泛型的
可以使用泛型,也可以不使用泛型
如果定义集合之后,没有使用泛型:元素在集合中都是Object接收
如果定义集合之后,使用了泛型,元素在集合中就是定义的类型
public class Arraylist_E <T> { ArrayList<T> a = new ArrayList<>(); }
//增强for循环遍历 for (String o:a){ System.out.println(o); //不用向下转型 } //迭代器遍历 ListIterator<String> it = a.listIterator(); while (it.hasNext()){ String s =it.next(); //不用向下转型 System.out.println(s); }
使用转数组:toArray方法遍历的时候,该方法的返回值固定是Object类型
所以使用元素的特殊方法时,也需要向下转型。
但是转数组,有另外一种方式:toArray(T[] arr)
在转数组的时候,可以自主准备一个数组,用来存储元素,数组可以和数据的类 型保持一致,那么在转换之后也不需要向下转型。
//转数组遍历 String[] strs = new String[a.size()]; for (int i = 0; i < strs.length; i++) { String s = strs[i]; System.out.println(s); }
概述:将来定义数据类型时,如果这个数据类型不确定,可以使用泛型来表示这个不确 定的类型;也可以使用泛型通配符来定义这个不确定的类型。
分类:
public static void main(String[] args) { ArrayList<Object> list1 = new ArrayList<>(); ArrayList<Integer> list2 = new ArrayList<>(); ArrayList<Number> list3 = new ArrayList<>(); ArrayList<String> list4 = new ArrayList<>(); getList1(list1); getList1(list2); getList1(list3); getList1(list4); public static void getList1(ArrayList<?> list){ } //都可以
public static void main(String[] args) { ArrayList<Object> list1 = new ArrayList<>(); ArrayList<Integer> list2 = new ArrayList<>(); ArrayList<Number> list3 = new ArrayList<>(); ArrayList<String> list4 = new ArrayList<>(); getList2(list1); //Object 不行 getList2(list2); //Integer 可以 getList2(list3); //Number 可以 getList2(list4); //String 不行 //? extends Number:表示可以接收Number类型或者Number子类类型 public static void getList2(ArrayList<? extends Number> list){ }
public static void main(String[] args) { ArrayList<Object> list1 = new ArrayList<>(); ArrayList<Integer> list2 = new ArrayList<>(); ArrayList<Number> list3 = new ArrayList<>(); ArrayList<String> list4 = new ArrayList<>(); getList3(list1); //Object 可以 getList3(list2); //Integer 不行 getList3(list3); //Number 可以 getList3(list4); //String 不行 //? super Number:表示可以接收Number类型或者Number父类类型 public static void getList3(ArrayList<? super Number> list){ }