泛型
泛型类泛型接口 泛型方法
非静态方法静态方法 泛型方法与可变参数通配符和上下限定
无界通配符通配符的上限限定通配符的下限限定 泛型总结
泛型泛型的本质是: 数据类型的参数化
把类型当作是参数一样传递<数据类型>只能是引用类型
泛型类泛型好处
不用强制转化
要编译时没有警告,运行时不会出现ClassCatException。
| 泛型标记 | 说明 |
|---|---|
| E(Element) | 在容器中使用,表示容器中的元素 |
| T(Type) | 表示普通的JAVA类 |
| K(Key) | 表示键,例如:Map中的键Key |
| V(Value) | 表示值 |
| N(Number) | 表示数值类型 |
| ? | 表示不确定的JAVA类型 |
package com.bjsxt02; public class fx{ private T flag; public void setFlag(T flag) { //使用泛型来定义参数类型 this.flag = flag; } public T getFlag() { return flag; } }
package com.bjsxt02;
public class Test {
public static void main(String[] args) {
fx f1=new fx<>(); //创建对象明确为String类型
f1.setFlag("admin");
String flag=f1.getFlag();
System.out.println(flag);
fx f2=new fx<>();
f2.setFlag(22);
int a=f2.getFlag();
System.out.println(a);
}
}
泛型接口
package com.bjsxt02; public interface Ifx{ T getName(T name); }
package com.bjsxt02; public class jk implements Ifx{//此时泛型要变成一个确定的类型 @Override public String getName(String name){ return name; } }
package com.bjsxt02;
public class Test2 {
public static void main(String[] args) {
jk j1=new jk();
String name=j1.getName("oldlu");
System.out.println(name);
Ifx f1=new jk();
String a=f1.getName("bjsxt");
System.out.println(a);
}
}
泛型方法
泛型类中所定义的泛型,在方法中也是可以使用的。
泛型方法是指将方法的参数类型定义成泛型,以便在调用时接收不同类型的参数。类型参数可以有多个,用逗号隔开。例如,
public<泛型表示符号> void getName(泛型表示符号 name){
}
public<泛型表示符号> 泛型表示符号 getName(){
}
package com.bjsxt02;
public class Method {
//非静态
public void setName(T name){
System.out.println(name); //可以是任何类型
}
//有返回值
public T getName(T name){
return name;
}
}
package com.bjsxt02;
public class Teat03 {
public static void main(String[] args) {
//无返回值
Method a1=new Method();
a1.setName("oldlu");
a1.setName(123);
//有返回值
Method a2=new Method();
String name1=a2.getName("北京");
System.out.println(name1);
Integer b=a2.getName(123321);
System.out.println(b);
}
}
静态方法
注意:静态方法无法访问类上定义的泛型,如果静态方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上。
public static <泛型表示符号> void getName(泛型表示符号 name){
}
public static <泛型表示符号> 泛型表示符号 getName(){
}
package com.bjsxt02;
public class Method {
public static void setFlag(T flag){
System.out.println(flag);
//这里的泛型是用方法里面的
}
public static T getFlag(T flag){
return flag;
}
}
package com.bjsxt02;
public class Test04 {
public static void main(String[] args) {
Method.setFlag("oldlu");
Method.setFlag(123321);
String flag=Method.getFlag("bjsxt");
System.out.println(flag);
Integer flag1=Method.getFlag(123321);
System.out.println(flag1);
}
}
泛型方法与可变参数
在泛型方法中,泛型也可以定义可变参数的类型。
public <泛型表示符号> void showMs(泛型表示符号… args){
}
package com.bjsxt02;
public class Method {
public void method(T... args){
for(T t:args){
System.out.println(t);
} //遍历
}
}
package com.bjsxt02;
public class Test05 {
public static void main(String[] args) {
Method a1=new Method();
String[] arr=new String[]{"a","b","c"};
a1.method(arr);
Integer[] arr2=new Integer[]{1,2,3,4,5,6};
a1.method(arr2);
}
}
通配符和上下限定
无界通配符
"?“表示类型通配符,用于代替具体的类型,它只能在”<>"中使用,可以解决当具体类型不确定的问题。
public void showFlag(Generic> generic){
}
package com.bjsxt02;
public class ShowMsg {
public void showFlag(fx> f1){ //如果要想为任何类型,必须为“?”
System.out.println(f1.getFlag());
}
}
package com.bjsxt02;
public class Test06 {
public static void main(String[] args) {
ShowMsg a1=new ShowMsg();
fx f1=new fx<>();
f1.setFlag(20);
a1.showFlag(f1); //一定要注意泛型不考虑继承
//Integer 的父类是Number类型
fx f2=new fx<>();
f2.setFlag(50);
a1.showFlag(f2);
fx f3=new fx<>();
f3.setFlag("aaa");
a1.showFlag(f3);
}
}
通配符的上限限定
上限限定表示通配符的类型是T类以及T类的子类或者T接口以及T接口的子接口。该方法同样适用于泛型的上限限定。
public void showFlag(Generic extends Number> generic){
}
package com.bjsxt02;
public class ShowMsg {
public void showFlag(fx extends Number> f1){ //表示泛型只能是Number类或者Number的子类
System.out.println(f1.getFlag());
}
}
package com.bjsxt02;
public class Test06 {
public static void main(String[] args) {
ShowMsg a1=new ShowMsg();
fx f1=new fx<>();
f1.setFlag(20);
a1.showFlag(f1); //一定要注意泛型不考虑继承
//Integer 的父类是Number类型
fx f2=new fx<>();
f2.setFlag(50);
a1.showFlag(f2);
}
}
通配符的下限限定
下限限定表示通配符的类型是T类以及T类的父类或者T接口以及T接口的子接口。注意:该方法不适用于泛型。
public void showFlag(Generic super Integer> generic){
}
package com.bjsxt02;
public class ShowMsg {
public void showFlag(fx super Number> f1){ //所限定范围在Number类和父类
System.out.println(f1.getFlag());
}
}
package com.bjsxt02;
public class Test06 {
public static void main(String[] args) {
ShowMsg a1=new ShowMsg();
fx f1=new fx<>();
f1.setFlag(20);
// a1.showFlag(f1); f1 会报错。因为Integer为Number的子类,不是父类
//Integer 的父类是Number类型
fx f2=new fx<>();
f2.setFlag(50);
a1.showFlag(f2);
}
}
泛型总结
泛型主要用于编译阶段,编译后生成的字节码class文件不包含泛型中的类型信息。类型参数在编译后不i被替换成Object,运行时虚拟机并不知道泛型,因此使用泛型时,如下几种情况是错误的。
1.基本类型不能用于泛型。
Test (int) t这种写法是错误的,我们可以使用对应的包装类: Test(Integer) t
2.不能通过类型参数创建对象。
T elm=new T(); 运行时类型参数T会被换成Object,无法创建T类型的对象,容易引起误解,所以在java中不支持这种写法。



