泛型引入:为什么需要泛型,
有时我们并不知道一个方法传入的参数或一个集合中数据是什么类型的, 如果对于每一种类型都单独定义一个方法或类型, 那样显得代码很臃肿, 再者如果你将接受参数类型设置为Object类型, 可以接受所有数据类型的数据, 但在使用的时候存在类型转换问题, 而且使用起来既不方便也不安全, 就有了泛型, 可以简单理解为在传入参数的时候会连同参数类型一起传入, 创建一个集合的时候可以指定一个集合中存放的数据类型
代码演示:
public class CustomizedGeneric {
public static void main(String[] args) {
Tiger<Integer, Double, String> tiger = new Tiger<>("泰哥", 1, 2.0, "你好");
Tiger<String, Boolean, Double> tiger2 = new Tiger<>("包包大人", "嘿嘿", true, 2.50);
System.out.println(tiger);
System.out.println(tiger2);
}
}
class Tiger<T, R, M> {
String name;
R r;
M m;
T t;
public Tiger(String name, T t, R r, M m) {
this.name = name;
this.r = r;
this.m = m;
this.t = t;
}
public void setName(String name) {
this.name = name;
}
public void setR(R r) {
this.r = r;
}
public void setM(M m) {
this.m = m;
}
public void setT(T t) {
this.t = t;
}
@Override
public String toString() {
return "Tiger{" +
"name='" + name + '\'' +
", t=" + t +
", r=" + r +
", m=" + m +
'}';
}
}
运行结果:
注意:
泛型不能作为类型创建数组, 因为不知道具体类型, 所以无法分配对应大小的空间; 也不能作为static方法的参数, 程序运行就会加载static修饰的方法, 而这个方法中参数的类型不确定, 所以也不能使用
要点:
1.Tiger 后面泛型, 所以把 Tiger 称之为泛型类
2.T,R,M 泛型的标识符, 一般是单个大写字母
3.泛型标识符可以有多个
4.普通成员可以使用泛型(属性, 方法)
5.使用泛型的类型不能初始化
6.静态方法不能使用泛型
泛型的具体使用代码:
public class GenericDemo {
public static void main(String[] args) {
Dog<String> dog1 = new Dog<>("小花");// 在定义一个Dog对象的时候就可以确定数据类型
dog1.show();// 打印对应的运行类型 class java.lang.String
/*
Dog<String> dog1 = new Dog<>("小花");这行代码相当于把Dog类变成了下面的这个样子
class Dog {
String name;
public Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void show() {
System.out.println(name.getClass());
}
}
*/
Dog<Integer> dog2 = new Dog<>(123);
dog2.show();// 打印对应的运行类型 class java.lang.Integer
/*
Dog<Integer> dog2 = new Dog<>(123);这行代码相当于把Dog类变成了下面的这个样子
class Dog {
Integer name;
public Dog(Integer name) {
this.name = name;
}
public Integer getName() {
return name;
}
public void show() {
System.out.println(name.getClass());
}
}
*/
// 如果没有指定泛型类型, 会根据传入参数进行判断, 传入的参数调用属于自己的getClass方法, 所以打印出来的是这个参数对应的 Class 类型
Dog dog3 = new Dog('1');
dog3.show();// class java.lang.Character
}
}
class Dog<E> {
E name;// 泛型可用于属性类型
public Dog(E name) {// 泛型可用于形参
this.name = name;
}
public E getName() {// 泛型可用于返回类型
return name;
}
public void show() {
System.out.println(name.getClass());
}
}
运行结果:
最后区别几个概念:
// 泛型类
class Fish<T, R> {
// 普通方法
public void swim() {}
// 泛型方法
// 1.<T, R> 就是泛型
// 2.是提供给 fly 使用的
public <U, M> void fly(U u, M m) {}
// 泛型方法, 既可以使用类声明的泛型, 也可以使用自己声明的泛型
public <U, M> void jump(T t, R r, U u, M m) {}
// 这不是个泛型方法, 只是使用的泛型
public void hi(T t) {}
// 当类声明的泛型和方法声明的泛型标识符重复时, 调用泛型方法时, 泛型方法的优先
public <T> void run(T t) {
System.out.println(t.getClass());
}
}