泛型概述(格式、好处)、泛型类、泛型方法、泛型接口、类型通配符、可变参数、可变参数的使用
泛型概述
泛型:是JDK5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测非法的类型,它的本质是参数类型化,也就是说所操作的数据类型被指定为一个参数 一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型。这种参数类型可以用在类、方法和接口中,分别被成为泛型类、泛型方法、泛型接口
定义格式:
<类型>:指定一种类型的格式。这里的类型可以看成是形参
<类型1,类型2 …>:指定多中类型的格式,多中类型之间用逗号隔开,这里的类型可以堪称是形参
将来具体调用的时候给定的类型可以看成实参,并且实参的类型只能是引用数据类型
泛型的好处:
1.把运行时间的问题提前到了编译期间
2.避免了强制类型转换
注意:
泛型的类型参数只能是引用类型,不能是基本类型。
使用尖括号 <> 声明一个泛型。
<>里可以使用T、E、K、V等字母。这些对编译器来说都是一样的,可以是任意字母。只是程序员习惯在特定情况下用不同字母来区分:
T : Type (类型)
E : Element(元素)
K : Key(键)
V : Value(值)
泛型类
泛型类定义格式:
格式:修饰符 class 类名<类型>{…}
范例:public class Generic<T>{…}
此处T可以随意写为任意标识,常见的标识如T、E、K、V等形式的参数常用于表示泛型
代码示例:
public class Student<T>{
private T t;
public void show( T t ){
System.out.println( t );
}
}
public static void main(String[] args){
Student<String> s = new Student<String>(); //泛型类在调用时的格式
s.show("字符串");
Student<Integer> s1 = new Student<Integer>();
s1.show(100);
Student<Boolean> s2 = new Student<Boolean>();
s2.show(true);
}
泛型方法
定义格式:
格式:修饰符<类型>返回值类型 方法名(类型 变量名){…}
范例:public<T> void show(T t){…}
代码示例:
public class Student{
public<T> void show( T t ){
//将方法定义为泛型方法
System.out.println(t);
}
public static void main(String[] args){
Student s = new Student();
s.show("字符串"); //泛型方法调用将自动把形参转换为相应类型
s.show(100);
s.show(true);
}
泛型接口
定义格式:
格式:修饰符 interface 接口名<类型>{…}
范例:public interface Generic<T>{…}
代码示例:
public interface Generic<T>{
//定义泛型接口
void show(T t);
}
public class Student implements Generic{
//定义实现类接收Generic接口 实现泛型类
@Override
public void show( Object t ){
//重写接口内方法
System.out.println( t );
}
public static void main(String[] args){
Generic<String> g = new Student(); //多态定义Generic 用Student实例化
g.show("字符串");
}
类型通配符
List<?>:表示元素类型未知的List,它的元素可以匹配任何类型
这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中
类型通配符上限:<? Extends 类型>
例子:List<? Extends Number>:它表示的类型是Number或者其子类型
类型通配符下限:<? Super 类型>
例子:List<? Super Number>:它表示的类型是Number或者其父类型
类型通配符一般使用?代替具体的类型参数。例如List<?>在逻辑上是List,List<具体类型实参>的父类
代码实例:
public static void main(String[] args) {
List<String> name = new ArrayList<String>();
List<Integer> age = new ArrayList<Integer>();
List<Number> number = new ArrayList<Number>();
name.add("icon");
age.add(18);
number.add(314);
getData(name);
getData(age);
getData(number);
}
public static void getData(List<?> data) {
//在函数形参设置类型通配符
System.out.println("data :" + data.get(0));
}
}
运行结果:
data:icon
data:18
data:314
可变参数
概述: 可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了
格式:修饰符 返回值类型 方法名(数据类型…变量名) {…}
范例:public static int sum(int…a){…}
可变参数注意事项:
- 这里的变量其实是一个数组
- 如果一个方法有多个参数,包含可变参数,可变参数要放在最后
代码示例:
public static int sum(int...a){
//注意:如果有多个参数则需要将函数定义为public static int sum(int b,int…a){…}
int sum=0;
for(inti : a){
sum + = i;
}
return sum;
}
public static void main(String[] args){
System.out.println(sum(10,20,30,40));
System.out.println(sum(90,100,110,120));
}
可变参数的使用
常用的可变参数集合:
Arrays工具类中有一个静态方法:
Public static<T> List<T> asList(T…a); //返回由指定数组支持的固定大小的列表
注:返回的集合不能做增删操作,可以做修改操作
List接口中由一个静态方法:
Public static<E> List <E> of(E…elements); //返回包含任意数量元素的不可变列表
注:返回的集合不能做增删改操作
Set接口中由一个静态方法:
public static <E> Set<E> of(E…elements); //返回一个包含任意数量元素的不可变集合
注:在给元素的时候,不能给重复的元素
返回的集合不能做增删操作,没有修改(set)方法
代码实例:
Public static void main(String[] args){
List<String> list = Arrays.asList("hello","world","java");
// list.add("javaee"); //UnsupportedOperationException
//list.remove(0); //UnsupportedOperationException
List.set(1,"javaee");
System.out.println( list );
List<String>list1=List.of("hello","world","java");
System.out.println(list1);
List.of(E…elements);
//该集合中add、set、remove等方法全会报错UnsupportedOperationException
Set<String>list2=Set.of("hello","wordl","java");
System.out.println(list2);
Set.of(E…elements);
//该集合中add、remove等方***报错UnsupportedOperationException 而且Set中没有set方法
}