泛型
没有泛型会有类型转换问题,存在隐患。(如Object类型转换)
黄色线:安全警告
三种声明(有历史)顾及老代码
泛型方法
自定义泛型:
- 修饰符 <声明自定义的泛型> 返回值类型 函数名(使用自定义泛型……)
- 字母是一个类型的占位符()
- 自定义泛型的具体数据类型是在调用该方法的时候传入实参是什么类型就是什么类型。
- 自定义泛型只要符合表示付的命名规则即可
- 但是一般是用的是一个大写字母表示,T Typt E element。
- 泛型不能用基本数据类型,不能用多态。
- 如果指定了泛型类的类型,还要另外指定泛型方法的类型,需要在方法上声明自定义泛型
泛型的好处:
1.将运行时的异常提前到编译时。
2.避免了强制类型转换。
/**
* 泛型测试
* @author 周太阳
*/
public class GenericityTest {
public static void main(String[] args) {
// 泛型方法
GenericityTest genericityTest = new GenericityTest();
Character method0 = genericityTest.method('a');
System.out.println(method0);
// 设置了泛型上限的方法
Double method3 = genericityTest.method3(123.0);
System.out.println(method3);
}
// 在没有声明泛型的类中不能这样定义
/*public T method(T t) {
return t;
}*/
/**
* 泛型方法
*/
public <T> T method(T t) {
return t;
}
/**
* 泛型的上限
* 设置了泛型上限传参就不能是其他没有继承的类
*/
public <T extends Number> T method3(T t) {
return t;
}
}
泛型类
泛型类的定义格式:
class 类名<声明的自定义泛型>{
}
泛型类要注意的事项:
- 泛型类是在将该泛型类实例化时确定的,这是该对象的泛型方法都是被指定的这个类型。如果要是用别的类型,要重新创建对象并指定泛型。
- 如果一个类上已经声明了泛型,但创建对象的时候没有规定泛型类型,默认是Object类型。
- 自定义类泛型,不能作用于静态方法,如果静态方法要自定义泛型,需要在返回值前面自定义泛型。(静态方法和普通方法的内存加载不同)
/**
* 泛型类
* @author 周太阳
* @param <T> 创建对象是指定什么,就是什么类型。
*/
class BaseGenericity<T>{
/**
* 泛型变量
*/
private T t;
public static void main(String[] args) {
// 不指定泛型,默认为Object类
BaseGenericity bg = new BaseGenericity();
Object method1 = bg.method(123);
System.out.println(method1);
System.out.println(bg.t);
// 指定泛型
BaseGenericity<Integer> bg1 = new BaseGenericity<Integer>();
Integer method2 = bg1.method(123);
System.out.println(method2);
// 在泛型类中的自定义泛型
String method3 = bg1.method3("123");
System.out.println("字符串:"+method3);
// 泛型变量跟随对象的的泛型
System.out.println(bg1.t.TYPE);
// 静态泛型
Boolean staticMethod = bg1.staticMethod(true);
System.out.println(staticMethod);
}
public T method(T t) {
System.out.println("泛型类"+getClass().getSimpleName());
// 可以写其他
int a = 2;
// 其他类也可以跟本类的泛型一致
GenericityInterface<T> test2 = new GenericityInterface<T>();
return t;
}
/**
* 报错
* @param 返回值是T泛型,这里就不能指定一个形参,
* 因为JVM不知道返回对不对
* @return
*/
/*public T method2(String s) {
System.out.println("泛型类"+getClass().getSimpleName());
return s;
}*/
/**
* 这样可以
*/
public String method2(T t) {
System.out.println(t);
return "泛型类";
}
/**
* 在泛型类中如果想要某个方法泛型不同,要自定义泛型
*/
public <E> E method3(E e) {
return e;
}
// 报错,因为静态方法的出现和普通方法出现的时间不同
/*public static T staticMethod1(T t) {
return t;
}*/
/**
* 静态方法的泛型必须要自定义泛型。因为静态方法比普通方法先出现
*/
public static <E> E staticMethod(E e) {
return e;
}
}
泛型接口
泛型接口的定义格式:
interface 接口名<声明的自定义泛型>{
}
泛型接口要注意的事项:
- 接口上自定义的泛型是在接口被实现时指定的,实现的接口的类的方法形参类型必须一致。
- 如果实现类不指定泛型类型默认是Object类型。
- 如果自定义泛型是T类型,必须在类上也要加上T,就可以创建本类对象的时候指定类型。
/**
* @param <T> 实现了泛型接口的类
* @author 周太阳
*/
public class GenericityInterface<T> implements InterfaceTest<T>{
public static void main(String[] args) {
// 带接口的泛型类
GenericityInterface<Double> gi = new GenericityInterface<Double>();
Double method = gi.method(6.666);
System.out.println(method);
// 泛型返回值上限
String method3 = gi.method3("123");
System.out.println(method3);
// 泛型形参上限
gi.method4(new GenericityInterface<Object>());
// 报错
// gi.method4(new GenericityInterface<Integer>());
// 接口为泛型下限
gi.method6(new GenericityInterface());
}
@Override
public T method(T t) {
System.out.println("泛型接口的类"+getClass().getSimpleName());
// 接口的泛型跟随类的创建而指定
GenericityInterface<String> gi = new GenericityInterface<String>();
// 调用实现接口重写的方法
String method = gi.method("123");
System.out.println(method);
return t;
}
@Override
public void method1(String str) {
}
/**
* 泛型的上限,指定T的范围可以是T的父类
* @param t
*/
public <T extends String> T method3(T t) {
return t;
}
/**
* 泛型的下限,使用通配符
* 可以返回GenericityInterface泛型为String的父类的对象
* @param t
*/
public GenericityInterface method4(GenericityInterface<? super String> t) {
return t;
}
/**
* 通配符的下限
*/
public GenericityInterface<? super Integer> method5(T t) {
GenericityInterface<Number> gi= new GenericityInterface();
// 普通泛型
Number method = gi.method(123);
// 泛型必须是String的子类,返回值类型是Object
Object method3 = gi.method3("123");
//返回test3报错,因为返回值界限是Integer的父类
// Test2<String> test3 = new Test2();
return gi;
}
/**
* 泛型的上限是接口
* @param t
*/
public <T extends InterfaceTest> T method5(T t) {
return t;
}
public GenericityInterface<? extends InterfaceTest> method6(GenericityInterface<? super InterfaceTest> t) {
GenericityInterface gi= new GenericityInterface();
return gi;
}
}
/**
*
* 实现接口的方法,形参与泛型不一样就会报错
*/
/*class Test2<T> implements InterfaceTest<String>{
@Override
public Integer method(Integer t) {
System.out.println("泛型接口的类"+getClass().getSimpleName());
Test2<String> test = new Test2<String>();
return 12;
}
}*/
/**
* @param <T> 泛型接口
*/
public interface InterfaceTest<T>{
T method(T t);
// 可以写其他方法
void method1(String str);
}
泛型的上下限
泛型中的通配符:?