泛型
概念:是一个未知的数据类型,是一个参数化类型
使用场景:
- 如果需要给一个类型定义属性,但是这个类型中的属性不确定,可以使用泛型来代替定义。
- 如果需要定义一个方法,但是该方法的参数列表类型和返回值类型不确定,可以使用泛型来定义。
泛型类 的定义与使用
在定义类型时,类上有泛型的使用,那么该类就是泛型类
格式:
class 类名<泛型>{
}
class person<T>{
private T name;
}
注意事项:
-
如果想要在类中使用泛型,首先需要在类的声明上,声明该泛型符号
-
如何定义泛型:
- 泛型符号可以是任意标识符
- 但是一般使用大写的字母来表示 M T Q L
-
如果一个类型定义了泛型,在使用这个类型的时候,可以确定泛型也可以不确定泛型。
-
如果不确定泛型的话:默认使用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);
}
泛型接口 的定义和使用
概述:如果接口中的抽象方法需要使用泛型,也需要先在接口上声明该泛型
注意:
- 将来接口的实现类如果实现了接口,但是没有指定泛型类型,在实现类中默认使用Object来表示该泛型。
//接口中应用泛型
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循环遍历
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){
}
//都可以
- ? extends E: 泛型通配符 可以表示泛型E类型或者泛型E类型子类类型
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){
}
- ? super E: 泛型通配符 可以表示泛型E类型或者泛型E类型的父类类型
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){
}
来源:https://blog.csdn.net/PIKapikaaaa/article/details/123243067
本站部分图文来源于网络,如有侵权请联系删除。