概念:
- 泛型是JDK1.5引入的新特性,也是最重要的一个特性。
- 泛型可以在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的。
- 泛型的原理就是“类型的参数化”,即把类型看做参数。也就是所,把所要操作的数据类型看做参数,就像方法的形式参数是运行时传递的值的占位符一样。
- 简单的说,类型变量 所扮演的角色就如同一个参数,它提供编译器用来类型检查的信息。
- 泛型可以提高代码的扩展性和重用性。
示例:
public class GenClass<T>{
//T 代表data的数据类型,在初始化的时候需要传入(String,Integer...)
T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
调用:
public void main(String[] args){
//这里初始化,传入数据类型为String
GenClass<String> class1 = new GenClass<String>();
class1.setData("zhangsan");
System.out.println(class1.getData());
}
特点:
- 泛型的类型参数可以是泛型类
- 泛型类可以同时设置多个类型参数,用“,”隔开
- 泛型类可以继承泛型类
- 泛型类可以实现泛型接口
示例:
新建一个类
class Student {
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static void main(String[] args) {
//实例化时,传入的类型是泛型类
GenClass<GenClass<Student>> gen1 = new GenClass<GenClass<Student>>();
GenClass<Student> gen2 = new GenClass<Student>();
gen2.setData(new Student("zhangsan"));
gen1.setData(gen2);
System.out.println(gen1.getData().getData().getName());
}
再新建一个泛型类,有两个类型参数:
public class GenClass1<T,P> {
private T data1;
private P data2;
public GenClass1(T data1,P data2) {
this.data1 = data1;
this.data2 = data2;
}
public T getData1() {
return data1;
}
public P getData2() {
return data2;
}
}
调用:
public static void main(String[] args) {
//这里传入参数类型,第一个为String,第二个为Integer
GenClass1<String,Integer> gen = new GenClass1<String,Integer>("zhangsan",10);
System.out.println(gen.getData1() + " " + gen.getData2());
}
新建一个泛型接口
interface GenInterface<T,T1>{
void ShowData(T data1,T1 data2);
}
新建一个泛型类GenClass2继承之前创建的GenClass和刚刚创建的泛型接口GenInterface:
class GenClass2<T, T1> extends GenClass implements GenInterface{
T1 data1;
public GenClass2(T data, T1 data1) {
super();
this.data = data;
this.data1 = data1;
}
public T1 getData1() {
return data1;
}
@Override
public void ShowData(Object data1, Object data2) {
System.out.println(data1 + " " + data2);
}
}
调用:
public static void main(String[] args) {
//这里传入参数类型,第一个为String,第二个为Integer
GenClass2<String,Integer> gen = new GenClass2<String,Integer>("zhangsan",10);
gen.ShowData(gen.getData(), gen.getData1());
}
限制泛型使用类型:
- 在定义泛型类别时,默认在实例化泛型类的时候可以使用任何类型,但是如果想要限制使用泛型类型时,只能使用某个特定类型或者其子类型才能实例化该类型时,可以在定义类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口。
- 当没有指定泛型继承的类或者接口时,默认使用extends object,所以默认情况下任何类型都可以作为参数传入
示例:
创建一个动物 Animal 接口,接口里面有一个eat方法:
interface Animal {
void eat();
}
创建一个Dog类实现Animal接口:
class Dog implements Animal {
@Override
public void eat() {
System.out.println("啃骨头");
}
}
创建一个Cat类也实现Animal接口:
class Cat implements Animal {
@Override
public void eat() {
System.out.println("吃鱼");
}
}
创建泛型类,限制泛型可用类型:
//泛型类所接受的类型做了限制,只能接受实现Animal接口的类或子类
class GenericClass<T extends Animal>{
private T obj;
public void setObj(T obj) {
this.obj = obj;
}
public T getObj() {
return obj;
}
}
调用:
public static void main(String[] args) {
//这里传入的数据类型是能是实现Animal接口的类或其子类
GenericClass<Dog> dogclass = new GenericClass<>();
dog.setObj(new Dog());
dog.getObj().eat();
GenericClass<Cat> catclass = new GenericClass<>();
cat.setObj(new Cat());
cat.getObj().eat();
}
类型通配声明:
- 同一泛型类,如果实例化给定的实际类型不同,则这些实例的类型是不兼容的,不能相互赋值。
如:
GenericClass<Dog> dogclass = new GenericClass<>();
GenericClass<Cat> catclass = new GenericClass<>();
dogclass = catclass;
将会编译报错,catclass不能赋值给dogclass。
-
泛型类实例之间的不兼容性会带来使用的不便,我们可以使用泛型通配符(?)声明泛型的变量就可以解决这个问题。
-
“?”代表任意一个类型。
如:
GenericClass<Dog> dogclass = new GenericClass<>();
GenericClass<?> animal = dogclass;
- 和限制泛型额上限相似,同样可以使用extends关键字限定通配符匹配类型的上限。
GenericClass<Dog> dogclass = new GenericClass<>();
//这里animal只能引用类型为Animal的子类对应的GenericClass
GenericClass<? extends Animal> animal = dogclass;
- 还可以使用super关键词将通配符匹配类型限定为某个类型及其父类型。
GenericClass<Dog> dogclass = new GenericClass<>();
//这里animal只能引用类型为Cat或其父类型所对应的GenericClass
GenericClass<? super Cat> animal = cat;
以上就是Java泛型的基本应用。
网友评论