泛型
为什么会有泛型呢?
早期的Object类型可以接收任意的对象类型,但是在实际的使用中,类型向下转换会有问题。也就存在隐患,所以Java提供了泛型来解决这个安全问题。泛型是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。即参数化类型,把类型当作参数一样的传递。
格式:<数据类型>,此处的数据类型只能是引用类型。
泛型好处
A:把运行时期的问题提前到了编译期间
B:避免了强制类型转换
C:优化了程序设计,解决了黄色警告线
泛型位置
类名后面
public class 类名<泛型类型K,泛型类型T>
方法返回值类型前面
public <泛型K> 返回类型 方法名(泛型K)
泛型类型
泛型类:public class 类名<泛型类型K,泛型类型T>
泛型类即把泛型定义在类名后面,格式:public class 类名<泛型类型K,泛型类型T>
package cn.itcast_04;
/*
* 泛型类:把泛型定义在类上
*/
public class ObjectTool<T> {
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
/*
* 泛型类的测试
*/
public class ObjectToolDemo {
public static void main(String[] args) {
ObjectTool<String> ot = new ObjectTool<String>();
//这个时候编译期间就过不去
//ot.setObj(new Integer(27));
ot.setObj(new String("林青霞"));
}
}
泛型方法:public <泛型K> 返回类型 方法名(泛型K)
泛型方法:把泛型定义在方法的返回值类型前面上,方法的参数和返回值都可以使用泛型
格式:public <泛型类型> 返回类型 方法名(<泛型类型>)
/*
* 1个泛型的泛型方法:把泛型定义在方法上,虽然泛型是在方法上使用但是可以看到泛型还是由类传递过来的。
* 这种是不纯粹的泛型方法
*/
public class ObjectTool<T> {
public T show(T t) {
System.out.println(t);
return t;
}
}
public class ObjectToolDemo {
public static void main(String[] args) {
//此处没有明确使用泛型类型,默认是 public class ObjectTool<T> extends Object
ObjectTool ot = new ObjectTool();
ot.show("hello");
ot.show(100);
ot.show(true);
//泛型类型String
ObjectTool<String> string = new ObjectTool<String>();
string.show("hello");
//泛型类型Integer
ObjectTool<Integer> integer = new ObjectTool<Integer>();
integer.show(100);
//泛型类型Boolean
ObjectTool<Boolean> bool = new ObjectTool<Boolean>();
bool.show(true);
}
}
输出:
hello
100
true
hello
100
true
/*
* 2个泛型的泛型方法:把泛型定义在方法上,虽然泛型是在方法上使用但是可以看到泛型还是由类传递过来的。
* 这种是不纯粹的泛型方法
*/
public class ObjectTool<T, K> {
public T show(T t) {
System.out.println(t);
return t;
}
public K show(T t, K k) {
System.out.println(t);
System.out.println(k);
return k;
}
public static void main(String[] args) {
ObjectTool<String, Integer> objectTool = new ObjectTool<>();
String cat = objectTool.show("cat");
Integer dog = objectTool.show("dog", 0);
}
}
纯粹的泛型方法
/*
* 泛型方法:把泛型定义在方法上
*/
public class ObjectTool {
public <T> T show(T t) {
System.out.println(t);
return t;
}
}
/*
* 使用时会根据传递参数的类型作为泛型的类型
*/
public class ObjectToolDemo {
public static void main(String[] args) {
ObjectTool ot = new ObjectTool();
//泛型String
ot.show("hello");
//泛型Integer
ot.show(100);
//泛型Boolean
ot.show(true);
}
}
泛型接口:public interface 接口名<泛型类型1>
把泛型定义在接口上
格式:public interface 接口名<泛型类型1…>
/*
* 泛型接口:把泛型定义在接口上
*/
public interface Inter<T> {
public abstract void show(T t);
}
//实现类在实现接口的时候
//第一种情况:已经知道该是什么类型的了
//public class InterImpl implements Inter<String> {
//
// @Override
// public void show(String t) {
// System.out.println(t);
// }
// }
//第二种情况:还不知道是什么类型的,在具体调用的时候才能确认
public class InterImpl<T> implements Inter<T> {
@Override
public void show(T t) {
System.out.println(t);
}
}
package cn.itcast_06;
public class InterDemo {
public static void main(String[] args) {
// 第一种情况的测试
// Inter<String> i = new InterImpl();
// i.show("hello");
//第二种情况的测试
Inter<String> i = new InterImpl<String>();
i.show("hello");
Inter<Integer> ii = new InterImpl<Integer>();
ii.show(100);
}
}
泛型高级(通配符)
?: 任意类型,Object以及任意的Java类了
? extends E: 向下限定,E及其子类
? super E: 向上限定,E及其父类
package digitalwallet;
import java.util.ArrayList;
import java.util.Collection;
/*
* 泛型高级(通配符)
* ?:任意类型,如果没有明确,那么就是Object以及任意的Java类了
* ? extends E:向下限定,E及其子类
* ? super E:向上限定,E极其父类
*/
public class GenericDemo {
public static void main(String[] args) {
// 泛型如果明确的写的时候,前后必须一致
Collection<Object> c1 = new ArrayList<Object>();
//编译报错
//Collection<Object> c2 = new ArrayList<Animal>();
// ?表示任意的类型都是可以的
Collection<?> c5 = new ArrayList<Object>();
Collection<?> c6 = new ArrayList<Animal>();
Collection<?> c7 = new ArrayList<Dog>();
Collection<?> c8 = new ArrayList<Cat>();
// ? extends E:向下限定,E及其子类
// 但是如果不是E及其子类就报错
// Collection<? extends Animal> c9 = new ArrayList<Object>();
Collection<? extends Animal> c10 = new ArrayList<Animal>();
Collection<? extends Animal> c11 = new ArrayList<Dog>();
Collection<? extends Animal> c12 = new ArrayList<Cat>();
// ? super E:向上限定,E及其父类
Collection<? super Animal> c13 = new ArrayList<Object>();
Collection<? super Animal> c14 = new ArrayList<Animal>();
// 但是如果不是E及其父类就报错
// Collection<? super Animal> c15 = new ArrayList<Dog>();
// Collection<? super Animal> c16 = new ArrayList<Cat>();
}
}
class Animal {
}
class Dog extends Animal {
}
class Cat extends Animal {
}
可变参数
可变参数概述
定义方法的时候不知道该定义多少个参数
格式:参数类型1 变量名1,参数类型2… 变量名2
修饰符 返回值类型 方法名(参数类型1 变量名1,参数类型2… 变量名2){}
注意事项
这里的变量2其实是一个数组,直接传数组也是没问题的。
如果一个方法有可变参数,并且有多个参数,那么,可变参数必须是最后一个。
Arrays工具类中的一个方法
public static List asList(T… a)
注意使用该方法转换成的List,长度不能改变,不能改变,不能改变。不能增删元素。可以改变内容
package digitalwallet;
import java.util.Arrays;
import java.util.List;
/*
* public static <T> List<T> asList(T... a):把数组转成集合
*/
public class ArraysDemo {
public static void main(String[] args) {
// 定义一个数组
// String[] strArray = { "hello", "world", "java" };
//虽然参数类型是一个可变参 但是直接传递一个数组也是没问题的
// List<String> list = Arrays.asList(strArray);
List<String> list = Arrays.asList("hello", "world", "java");
//虽然可以把数组转成集合,但是集合的长度不能改变。可以改变内容
// UnsupportedOperationException
// list.add("javaee");
// UnsupportedOperationException
// list.remove(1);
list.set(1, "javaee");
for (String s : list) {
System.out.println(s);
}
}
}
package cn.itcast_03;
/*
* 可变参数:定义方法的时候不知道该定义多少个参数
* 格式:
* 修饰符 返回值类型 方法名(数据类型… 变量名){
*
* }
*
* 注意:
* 这里的变量其实是一个数组
* 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个
*/
public class ArgsDemo {
public static void main(String[] args) {
// 2个数据求和
int a = 10;
int b = 20;
int result = sum(a, b);
System.out.println("result:" + result);
// 3个数据的求和
int c = 30;
result = sum(a, b, c);
System.out.println("result:" + result);
// 4个数据的求和
int d = 30;
result = sum(a, b, c, d);
System.out.println("result:" + result);
// 需求:我要写一个求和的功能,到底是几个数据求和呢,我不太清楚,但是我知道在调用的时候我肯定就知道了
// 为了解决这个问题,Java就提供了一个东西:可变参数
result = sum(a, b, c, d, 40);
System.out.println("result:" + result);
result = sum(a, b, c, d, 40, 50);
System.out.println("result:" + result);
}
public static int sum(int... a) {
// System.out.println(a);
//return 0;
int s = 0;
for(int x : a){
s +=x;
}
return s;
}
// public static int sum(int a, int b, int c, int d) {
// return a + b + c + d;
// }
//
// public static int sum(int a, int b, int c) {
// return a + b + c;
// }
//
// public static int sum(int a, int b) {
// return a + b;
// }
}