1、泛型
泛型本质就是参数化类型,也就是所操作的数据类型被指定为一个参数。
参数类型理解:将类型有原来的具体类型参数化,然后在使用/调用时传入具体的类型
这种参数化类型可以用在类上 方法 和接口上,分别被称为泛型类 泛型方法 泛型接口
泛型是指在定义集合的同时也定义集合中元素的类型,需要“< >”进行指定,其语法形式如下。
集合<数据类型> 引用名 = new 集合实现类<数据类型> ();
需要注意,使用泛型约束的数据类型必须是对象类型,而不能是基本数据类型。如下就限制了 List 集合中只能存放 String 类型的元素。
List<String> list = new ArrayList<String>();
在 JDK1.7 之后,=右边< >中的的 String 等类型也可以省略,例如以上代码可以写成以下的等价形式。
List<String> list = new ArrayList<>();
自定义泛型:
修饰符 class 类名<T>
此处的T 可以使任意标识符 常见的有T E K V
泛型方法:
格式 修饰符 <T> 返回值类型 方法名(形参列表)
泛型接口:
修饰符 interface 接口名<T>
泛型通配符<?>:
为了表示泛型List的父类 可以使用类型通配符
List<?> 表示元素类型是未知的List 他的元素可以匹配任何类型
这种带通配符的List进表示他是各种泛型List的父类,并不能把元素添加到其中
List<?> list = new LinkedList<>();//是所有list的父类
list.add("aaaa");//此操作不可以
list.add(123);//此操作不可以
如果我们不希望List<?>是任何泛型List的父类,只希望他代表某一类List的父类 可以使用类型通配符的上限
类型通配符的上限: <? extends 类型>
List<? extends Number> 表示的类型是Number或者Number的子类
除了可以指定类型通配符的上限 还可以指定他的下限
类型通配符的下限:<? super 类型>
List<? super Number> 表示类型是Number或者Number 的父类
通配符的基本用法:
public class GenericTest {
public static void main(String[] args) {
List<?> list = new LinkedList<Object>();//是所有list的父类
List<?> list1 = new LinkedList<Number>();//是所有list的父类
List<?> list2 = new LinkedList<Integer>();//是所有list的父类
// list.add("aaaa");//此操作不可以
// list.add(123);//此操作不可以
System.out.println("----------通配符的上限------------");
List<? extends Number> list3 = new ArrayList<Number>();
List<? extends Number> list4 = new ArrayList<Integer>();
// List<? extends Number> list5 = new ArrayList<Object>();
System.out.println("----------通配符的下限------------");
List<? super Number> list6 = new ArrayList<Number>();
//List<? super Number> list7 = new ArrayList<Integer>();
List<? super Number> list8 = new ArrayList<Object>();
System.out.println("----------通配符------------");
List<String> strList = new ArrayList<>();
strList.add("aaa");
strList.add("bbb");
strList.add("ccc");
List<?> listSuper = strList;
for(int i = 0 ; i < listSuper.size();i++){
System.out.println(listSuper.get(i));
}
/*
通过以上代码 那么我们可以发现他的用法:可以在需要使用集合做参数的时候,我们知道该参数一个List
但是却又不知道他的泛型类型,此时为了提高代码的通用性和扩展性,此时可以使用通配符
接收实参时,则可以接收任意的集合。
*/
}
}
泛型擦除:
public static void main(String[] args) {
List<String> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
//通过java的反射机制 可以获取每个类的唯一的表示 Class
Class c1 = list1.getClass();
Class c2 = list2.getClass();
System.out.println(c1);//class java.util.ArrayList 得到的类型 没有泛型信息 泛型只在编译期有效
System.out.println(c1 == c2);//在运行时 泛型丢失的现象称为泛型擦除
}
2、可变参数
可变参数又称为参数个数可变,用作方法的形参,方法的参数的个数就可变了
格式:
修饰符 返回值类型 方法名(数据类型...变量名) 表明该方法可以接收数据类型指定类型的0个或多个参数
public class ArgsDemo {
// 计算整数的和
public static int sum(int ... a){
int sum = 0 ;
//可变参数的用法同数组
for(int i = 0 ; i <a.length;i++){
sum+=a[i];
}
return sum;
}
public static void main(String[] args) {
System.out.println(sum(10));
System.out.println(sum(10,20,30));
System.out.println(sum());
}
}
可变参数的使用的注意事项:
// 计算整数的和 次方法至少需要一个整数
public static int sum(int x,int ... a){
int sum = x ;
//可变参数的用法同数组
for(int i = 0 ; i <a.length;i++){
sum+=a[i];
}
return sum;
}
在一个方法中,如果包含多个参数,其中有一个可变参数,可变参数必须放在参数列表末尾
public static double sum(double x,int y,int ... a){
double sum = x ;
//可变参数的用法同数组
for(int i = 0 ; i <a.length;i++){
sum+=a[i];
}
return sum;
}