在解释泛型的时候先说下java中的可变参数的定义和应用。
定义:参数的类型... 参数名称
示例:
public class Demo{
public static void main(String args[]){
System.out.println(count(1,2,2,3,4));
}
public static int count(int... temp){//使用可变参数的形式完成需求
int sum=0;
for(int i=0;i<temp.length;i++){
sum+=temp[i];
}
return sum;
}
```
泛型:java的一个新特性,相当于是一个标签。在集合中大量使用。
在定义一个类的时候如果无法确定某些参数的类型的时候,可以先不去确定参数的类型,先使用一个占位符<T>的形式表示参数类型。等创建对象的时候再具体确定参数的形式。泛型的出现是为了让运行时的错误在编译时体现出来。让开发跟快捷。
为什么要用泛型:
package com.zhaoqiang.paradigm;
import java.util.ArrayList;
/*
- 泛型:
- 需求:把一个集合中元素全部转成大写
- */
public class Demo1 {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("aa");
list.add("bb");
list.add("cc");
list.add(123);
for (int i = 0; i < list.size(); i++) {
String str = (String)list.get(i);
System.out.println("大写"+str.toUpperCase());
}
}
}
上面的代码出现了一个异常“ClassCastExcepton”,出现这个异常的根本原因就是int 类型的数据不能转换成String类型的数据。所有我们需要避免这种错误发生在运行时(如果你不声明泛型,项目内开发的时候,其他人很难知道你这个集合存放的是什么数据类型)
示例:
package com.zhaoqiang.paradigm;
import java.util.ArrayList;
/*
- 泛型:
- 需求:把一个集合中元素全部转成大写
- */
public class Demo1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("aa");
list.add("bb");
list.add("cc");
list.add(123);
for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
System.out.println("大写"+str.toUpperCase());
}
}
}
上面的代码在编辑的时候就会出现错误(安全警告),因为这个时候集合中只能存放String类型的数据。也避免了无谓的强制类型转换。
下面介绍一下方法上定义泛型:
修饰符 <声明自定义的泛型> 返回值类型 函数名(使用自定义泛型){}
示例:
package com.zhaoqiang.paradigm;
/*
- 需求:定义一个方法可以接受任意类型的参数,而且返回值类型必须要与实际参数一致。
- 自定义泛型:
自定义泛型就是一个数据类型的占位符或者是一个数据类型的变量
- 在方法上自定义泛型:
修饰符 <声明自定义的泛型> 返回值类型 函数名(使用自定义泛型){
}
- 注意:在泛型中不能使用基本数据类型,如果需要使用基本数据类型,那么久使用基本数据类型对于的包装类型。
- byte --- Byte
- short -- Short
- int ---- Integer
- long --- Long
- double - Double
- float -- Float
- char --- Character
- boolean - Boolean
- 方法泛型注意事项:
1,在方法上自定义泛型,这个自定义泛型的具体数据类型是在调用该方法的时候传入实参是确定。
2,自定义泛型只要符合标识符的命名规则即可。但是一般习惯自定义泛型的时候使用一个大写字母表示(T(Type),E(Element))
- */
class Person<T>{
public T say(T t){
return t;
}
}
public class Demo2 {
public static void main(String[] args) {
String str = getData("abc");
System.out.println(str.toUpperCase());
}
public static <T>T getData(T t){
return t;
}
public static <T>Person getInfo(Person<T> p){
return p;
}
public static void getInfo(Person<Integer> p){
System.out.println(p);
}
public static String getInfo(Person<String> p){
return p.say("hah");
}
}
上面的泛型类型是在使用的时候(调用的时候确定泛型的数据类型).
如果一个类里面很多个方法都要用到泛型。我们可以定义一个泛型类:
class 类名<泛型>{}
示例:
class MyArrays<T>{
// 元素翻转
public void reverse(T[] arr){
for (int startIndex=0, endIndex=arr.length-1; startIndex<endIndex; startIndex++,endIndex--){
T temp = arr[startIndex];
arr[startIndex] = arr[endIndex];
arr[endIndex] = temp;
}
}
public String toString(T[] arr){
StringBuffer sb = new StringBuffer();
for (int i = 0; i < arr.length; i++) {
if (i==0) {
sb.append("["+arr[i]+",");
}else if(i==arr.length-1){
sb.append(arr[i]+"]");
}else{
sb.append(arr[i]+",");
}
}
return sb.toString();
}
// 如果使用静态修饰了方法,必须要用这种格式。
// 原因:自定义在类上的泛型是不会作用在静态方法上的
public static <T> void print(T[] t){
}
}
public class Demo3 {
public static void main(String[] args) {
Integer[] arr = {10,15,48,456,742};
MyArrays<Integer> marr = new MyArrays<Integer>();
marr.reverse(arr);
System.out.println(marr.toString(arr));
}
}
通过上面的代码可以证明开始说的那句话,在类上定义泛型的具体数据类型是在使用该类创建对象的时候确定的。【注】泛型没有重载。
泛型的上限和下限:
上限:<? extends T>
一旦在方法中指定了泛型的上限,那么该方法只能接收上限所对应的类的子类类型的泛型或者上限对应的本类类型。
下限:<? super T>
一旦设置了下限,那么方法所接受的类型必须是下限所对应的父类及本类类型。
示例:
public class Demo5 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
ArrayList<Number> list2 = new ArrayList<Number>();
print(list);
print(list);
HashSet<String> set = new HashSet<String>();
ArrayList<String> set1 = new ArrayList<String>();
printl(set1);
printl(set);
}
// 泛型的下限
public static void print(Collection<? super Integer> c){
}
// 泛型的下限
public static void printl(Collection<? extends String> c){
}
}
泛型接口:
interface IAction<T>{//定义一个泛型接口
public T count(T t);
}
class Action<T> implements IAction<T>{
public T count(T t){
return t;
}
}
public class Demo {
public static void main(String[] args) {
System.out.println( new Action<Double>().count(12.0));
}
}
网友评论