泛型
让一个类或一个方法或一个接口能支持多种不同的数据类型
(一套代码可用于多种类型)
泛型分类
1.泛型类
语法
class 类名<泛型参数列表> {
//类体
}
如
class ClassName<T, S> {
public T name;
public S age;
public ClassName(T name, S age) {
this.age = age;
this.name = name;
}
}
注意:这里的T和S在实例化类的时候需要指定,且只能指定为引用类型,如果是内在类型,需要使用包装类
在泛型类中不能创建实例,需要在构造函数中传入
这样就会出错
class ClassName<T, S> {
public T name;
public S age;
public ClassName() {
this.age = new T();
this.name = new S();
}
}
java: 意外的类型
需要: 类
找到: 类型参数T
泛型类实例化
类名<类型参数列表> 对象名 = new 类名<类型参数列表>();
上述例子的实例化为
ClassName<String,Integer> object = new ClassName<String, Integer>();
如果不用包装类,写成这样
ClassName<String, Integer> object = new ClassName<>("123", 5);
就会报错
java: 意外的类型
需要: 引用
找到: int
实例化的时候可以简化
如:省略右侧的参数列表
ClassName<String,Integer> object2 = new ClassName<>();
左侧的尖括号如果省略了,T和S就变成了Object类型了,右侧的尖括号如果省略了,new出来的对象也变成Object类型了
这两种情况都不是我们所指定的类型<Stirng,int>
类型边界
用来约束泛型参数的
语法
class 类名<T extends U> {
//类体
}
在实例化时,T只能为U的子类或者是U本身,否则编译出错
如果未写extends U这样的语句即未指定边界类型,可以看作是extends Object
class A<T> { }
即为
class A<T extends Object> { }
2.泛型方法
语法
方法限定符 <类型参数列表> 返回值类型 方法名(形参列表) {
方法体
}
例子
public class Test {
public static void main(String[] args) {
fun(new String("123"), 2);
}
public static <T, S> boolean fun(T a, S b) {
return true;
}
}
调用fun方法的时候,不必写传入的参数,编译器会自动判断
通配符
?
用在泛型,表示通配符
用于方法的参数是泛型类
class ClassName<T, S> {
public T name;
public S age;
public ClassName(T name, S age) {
this.age = age;
this.name = name;
}
}
public class Test {
public static void main(String[] args) {
fun(new ClassName<>("张三",16));
}
public static void fun(ClassName<?,?> object) { }
}
<? extends U>
语法-上界
<? extends U>
表示传入的类型(?为传入的类型)只能是U的子类或者U本身
如:
class Animal { }
class Dog extends Animal { }
class Cat extends Animal { }
class Bird extends Animal { }
class ClassName<T> { }
public class Test {
public static void main(String[] args) {
fun(new ClassName<Dog>());
fun(new ClassName<Animal>());
}
public static void fun(ClassName<? extends Animal> a) { }
}
这样写没有任何问题,Dog类、Cat类、Bird类都是继承于Animal类
但是这样写就会出问题
fun(new ClassName<Object>());
结果
java: 不兼容的类型: ClassName<java.lang.Object>无法转换为ClassName<? extendsAnimal>
Object类不是Animal类的子类是它的父类
<? super U>
语法-下界
<? super U>
表示传入的类型(?为传入的类型)只能是U的父类或者U本身
class Creature { }
class Person extends Creature { }
class Student extends Person { }
class UniversityStudent extends Student { }
class ClassName<T> { }
public class Test {
public static void main(String[] args) {
fun(new ClassName<UniversityStudent>());
fun(new ClassName<Person>());
}
public static void fun(ClassName<? super UniversityStudent> x) { }
}
这里UniversityStudent类的父类是Student类、Person类、Creature类、Object类所以fun方法里可以传入这些对象
3.泛型接口
语法
interface 接口名<泛型参数列表> {
//接口体
}
例子
interface Comparable<T> {
public int compareTo(T o);
}
类型擦除
将所有的泛型表示替换为具体的类型
实际的下面代码
class ClassName<T, S, V> {
private T field1;
private S field2;
private V field3;
public ClassName(T t, S s, V v) {
this.field1 = t;
this.field2 = s;
this.field3 = v;
}
}
会在编译的时候可能替换成
class ClassName {
private Object field1;
private Object field2;
private Object field3;
public ClassName(Object t, Object s, Object v) {
this.field1 = t;
this.field2 = s;
this.field3 = v;
}
}
类型擦除也有规则,这里具体就不说了,感兴趣的读者可以查阅资料
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/122861.html