泛型
什么是泛型?
所谓泛型,就是一种不确定的数据类型。
泛型意味着编写的代码可以被不同类型的对象所调用。
为什么要提出泛型?
泛型的提出,是为了编写重用性更好的代码;
当我们在是使用泛型的时候,即指定了数据类型,又可以根据需要灵活使用不同数据类型,在使用严谨性与灵活性之间做了一个很好的兼顾。
主要是为了灵活使用各种数据类型
泛型的本质是什么?
是参数化类型,也就是说 所操作的数据类型被指定为一个整数。
泛型类
- 格式:
public class 类名<泛型表示符号> { } - 示例代码:
泛型类:
package com.FanXing;
/**
* 泛型类
* 泛型类的具体使用方法是在类的名称之后添加一个或者多个类型参数声明 如:<T> <T,K,V>
* T: 表示普通的java类
* @param <T>
*/
public class Generic <T>{
private T flag;
public T getFlag() {
return flag;
}
public void setFlag(T flag) {
this.flag = flag;
}
}
调用泛型类:
package com.FanXing;
/**
* 我们在Test类内调用泛型类
*/
public class Test {
public static void main(String[] args) {
Generic<String> generic = new Generic<>();
generic.setFlag("admin");
String flag = generic.getFlag();
System.out.println(flag);
Generic<Integer> generic1 = new Generic<>();
generic1.setFlag(100);
Integer flag1 = generic1.getFlag();
System.out.println(flag1);
}
}
输出结果:
泛型接口
- 格式:
public interface 接口名<泛型表示符号> { }
- 示例代码:
创建一个泛型接口:
package com.FanXing;
/**
* 泛型接口
*/
public interface Generic2<T>{
T getName(T name);
}
创建一个接口实现类:
package com.FanXing;
/**
* 创建一个 接口实现类
*/
public class IgenericImpl implements Generic2<String> {
@Override
public String getName(String name) {
return name;
}
}
使用泛型接口实现类输出数据:
package com.FanXing;
public class Test2 {
public static void main(String[] args) {
//使用自定义的接口实现类IgenericImpl 输出String类型的数据
IgenericImpl igeneric = new IgenericImpl();
String name = igeneric.getName("OldLiu");
System.out.println(name);
//利用自定义的泛型接口Generic2 输出一个String 类型的数据
Generic2<String> igeneric1 = new IgenericImpl();
String name1 = igeneric1.getName("OleLiu2");
System.out.println(name1);
}
}
输出结果:
泛型方法
调用泛型方法时,不需要像泛型类那样告诉编译器是什么类型,编译器可以自动推 断出类型来。
泛型方法分为非静态泛型方法和静态泛型方法
非静态泛型方法
- 格式:
public <泛型表示符号> void getName(泛型表示符号 name){ }
public <泛型表示符号> 泛型表示符号 getName(泛型表示符号 name){ }
- 示范代码(分为有返回值和无返回值的两种非静态泛型方法):
package com.FanXing;
/**
* 泛型方法:
* 当我们不想将泛型定义在类 上,可以在方法内定义泛型
*/
public class MethodGeneric {
//定义一个非静态的泛型方法
public <T> void setName(T name){
System.out.println(name);
}
//定义一个有返回值的非静态的泛型方法
public <T> T getName(T name){
return name;
}
}
package com.FanXing;
public class Test3 {
public static void main(String[] args) {
MethodGeneric methodGeneric = new MethodGeneric();
//调用泛型方法时,不需要像泛型类那样告诉编译器是什么类型,编译器可以自动推 断出类型来。
methodGeneric.setName("aaaa");
System.out.println("==============");
//调用有返回值的方法
MethodGeneric methodGeneric1 = new MethodGeneric();
String name1 = methodGeneric1.getName("bjsxt");
int name2 = methodGeneric1.getName(123);
System.out.println(name1);
System.out.println(name2);
}
}
测试结果:
静态泛型方法
- 格式:
public static <泛型表示符号> void setName(泛型表示符号 name){ }
public static <泛型表示符号> 泛型表示符号 getName(泛型表示符号 name){ }
- 示范代码:
package com.FanXing;
public class MethodGeneric {
//静态方法无返回值
public static <T> void setFlag(T flag){
System.out.println(flag);
}
//静态方法没有返回值
public static<T> T getFlag(T flag){
return flag;
}
}
package com.FanXing;
public class Test4 {
public static void main(String[] args) {
//调用没有返回值的静态方法
MethodGeneric.setFlag("OLdLiu");
MethodGeneric.setFlag(123);
//调用有返回值的静态方法
String flag = MethodGeneric.getFlag("Bjsxt");
System.out.println(flag);
Integer flag1 = MethodGeneric.getFlag(12345);
System.out.println(flag1);
}
}
测试结果:
泛型无界通配符
package com.FanXing;
/**
* 无界通配符的使用
* Generic<String>: 当我们将泛型指定为String类型时,showFlag对于Generic的操作只能是String类型
* 所以我们引入无界通配符,格式为:Generic <?>
*/
public class ShowMsg {
public void showFlag(Generic<?> generic){
System.out.println(generic.getFlag());
}
}
package com.FanXing;
/**
* 对于ShowMsg类的无界通配符的实践
*/
public class Test5 {
public static void main(String[] args) {
ShowMsg showMsg = new ShowMsg();
Generic<Integer> generic = new Generic<>();
generic.setFlag(20);
showMsg.showFlag(generic); //showFlag方法可以操作Integer类型
Generic<Number> generic1 = new Generic<>();
generic1.setFlag(30);
showMsg.showFlag(generic1); //showMsg方法也可以操作Number类型
Generic<String> generic2 = new Generic<>();
generic2.setFlag("Bjsxt");
showMsg.showFlag(generic2); //showMsg方法也可以操作String类型
}
}
测试结果: