1.什么是泛型
泛型是指参数化类型。就是把类型像参数一样传递
2.泛型的作用
3.泛型的定义
泛型字符
泛型字符可以是任何标识符,一般采用几个标记:E T K V N。
| 泛型标记 | 对应单词 | 说明 |
|---|---|---|
| E | element |
在容器中使用,表示容器中的元素
|
| T | type |
表示普通的 JAVA 类
|
| K | key |
表示键,例如:Map 中的键 Key
|
| V | value | 表示值 |
| N | Number | 表示数值类型 |
| ? |
表示不确定的 JAVA 类型
|
泛型类
public class 类名<泛型标识符>{
}
public class Generic<T> {
private T flag;
public void setFlag(T flag){
this.flag = flag;
}
public T getFlag(){
return this.flag;
}
}
泛型接口
public interface 接口名<泛型标识符>{
}
public interface Interface1<T> {
T fun(T name);
}
实现接口泛型类
非静态方法 且 无返回值(void)
public <泛型标识符> void fun(<泛型标识符> a){
}
public void setFlag(T flag){
this.flag = flag;
}
非静态方法 且 有返回值
public <泛型标识符> <泛型标识符> fun(<泛型标识符> a){
}
public T getFlag(){
return this.flag;
}
对上面两个方法的test
// 泛型测试
public class Test {
public static void main(String[] args) {
Generic<String> generic = new Generic<>();
generic.setFlag("xdw");
String flag = generic.getFlag();
System.out.println(flag);
//
Generic<Integer> generic1 = new Generic<>();
generic1.setFlag(100);
Integer flag1 = generic1.getFlag();
System.out.println(flag1);
}
}
// 输出为
//xdw
//100
参数可变泛型方法
public <泛型标识符> <泛型标识符> fun(<泛型标识符>...a){
}
public class args_generic_test {
public static void main(String[] args) {
EDG edg = new EDG();
String[] strings = new String[]{"edg","rng","tes"};
Integer[] integers = new Integer[]{1,2,3};
edg.method(strings);
edg.method(integers);
}
}
class EDG{
public <T> void method(T...args){
for(T t:args){
System.out.println(t);
}
}
}
/*
输出为
edg
rng
tes
1
2
3*/
静态方法 且 无返回值(void)
public static <泛型标识符> void fun(<泛型标识符> a){
}
public static <T> void getStr(T Str){
System.out.println("Str:"+Str);
}
静态方法 且 有返回值
public static <泛型标识符> <泛型标识符> fun(<泛型标识符> a){
}
public static <T> T getStr1(T Str){
return Str;
test
public class static_method_gengeric_test {
public static void main(String[] args) {
A a = new A();
a.getStr("无返回值静态泛型Test");
String aa = a.getStr1("有返回值静态泛型Test");
System.out.println("Str:"+aa);
}
}
4.通配符上下限定
extends : 上限限定
比如 <? extends Number> 那么传入的类型只能是Number和number的子类
super : 下限限定
比如 <? super Number> 那么传入的类型只能是Number和number的父类(爷爷也可以)
// super 下线限定的test
/*
* 限定能用的是Number和他的父类(包括爷爷)*/
public class limit_generic {
public static void main(String[] args) {
A2 a2 = new A2();
Generic<Integer> generic = new Generic<>(); // 自己
Generic<Number> generic1 = new Generic<>(); // 父类
// Generic<String> generic2 = new Generic<>();
Generic<Object> generic3 = new Generic<>(); // 爷爷
generic.setFlag(11);
a2.method2(generic);
generic1.setFlag(50);
a2.method2(generic1);
// a2.method2(generic2);
generic3.setFlag(555);
a2.method2(generic3);
}
}
class A2{
public void method2(Generic<? super Integer> name){
System.out.println("通配符下线限定");
System.out.println("限定类型为Integer和它的父类");
System.out.println("当前的值:"+name.getFlag());
}
}
5.总结
泛型主要用于编译阶段,编译后生成的字节码 class 文件不包含泛型中的类型信息。
类型参数在编译后会被替换成 Object,运行时虚拟机并不知道泛型。
因此,使用泛型时,如下 几种情况是错误的:
1. 基本类型不能用于泛型。 Test<int> t; 这样写法是错误,我们可以使用对应的包装类;Test<Integer> t ;
2. 不能通过类型参数创建对象。 T elm = new T(); 运行时类型参数 T 会被替换成 Object,无法创建 T 类型的对象,容 易引起误解,所以在 Java 中不支持这种写法
本文详细介绍了Java泛型的概念、作用,展示了如何在类、接口和方法中使用泛型,并通过实例演示了参数可变泛型和通配符上下限。重点讲解了泛型在编译期的优势及常见误区,适合开发者提升代码质量和安全性。
478

被折叠的 条评论
为什么被折叠?



