引入泛型知识的过渡
首先写两个类作为辅助类,一个类作为测试类
辅助类为C1和C2,测试类为Test
C1的代码
package Java泛型;
public class C1 {
private Integer a;
public C1(Integer a) {
super();
this.a = a;
}
public Integer getA() {
return a;
}
public void setA(Integer a) {
this.a = a;
}
public void print(){
System.out.println("a的类型是:"+a.getClass().getName());
}
}
C2的代码
package Java泛型;
public class C2 {
private String a;
public C2(String a) {
super();
this.a = a;
}
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public void print(){
System.out.println("a的类型是:"+a.getClass().getName());
}
}
Test的代码
package Java泛型;
public class Test {
public static void main(String[] args) {
C1 c1=new C1(1);
c1.print();
int i=c1.getA();
System.out.println("i="+i);
C2 c2=new C2("hi");
c2.print();
int i2=c1.getA();
System.out.println("i2="+i2);
}
}
看一下效果
很显然,这样写的话,在C1和C2里面有超级多的重复的部分,这样代码的重复度就太高了,可浏览的有价值的部分真的很少,而且还很麻烦!怎么解决呢?首先想到的是用一个Object类去取代这些,因为Object类是所有类的父类。
C12是Object类取代的C1和C2这两个类
C12代码
package Java泛型;
public class C12 {
private Object object;
public C12(Object object) {
super();
this.object = object;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
public void print(){
System.out.println("object的类型是:"+object.getClass().getName());
}
}
再看看测试代码
package Java泛型;
public class Test {
public static void main(String[] args) {
C1 c1=new C1(1);
c1.print();
int i=c1.getA();
System.out.println("i="+i);
C2 c2=new C2("hi");
c2.print();
int i2=c1.getA();
System.out.println("i2="+i2);
C12 c12=new C12(1);//向上转型,安全的
c12.print();
int i12=(int)c12.getObject();//向下转型,不安全的
System.out.println("i12="+i12);
C12 c122=new C12("hello");//向上转型,安全的
c122.print();
String i122=(String)c122.getObject();//向下转型,不安全的
System.out.println("i122="+i122);
}
}
效果
虽然一个类取代了两个类,但是!又有问题出现了,我们需要对数据进行强转,强转是一种很不安全的做法,下面就要开始引入泛型了。
泛型的实现简单实现
写一个泛型类,取代上面的C1,C2,C12,泛型类命名为CC
CC的代码:
package Java泛型;
//用什么字母都是可以的,一般的情况是用T
public class CC<T> {
private T t;
public CC(T t) {
super();
this.t = t;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public void print(){
System.out.println("T的类型是:"+t.getClass().getName());
}
}
测试类沿用上面的Test,直接在Test中创建CC类的对象
代码如下:
package Java泛型;
public class Test {
public static void main(String[] args) {
C1 c1=new C1(1);
c1.print();
int i=c1.getA();
System.out.println("i="+i);
C2 c2=new C2("hi");
c2.print();
int i2=c1.getA();
System.out.println("i2="+i2);
C12 c12=new C12(1);//向上转型,安全的
c12.print();
int i12=(int)c12.getObject();//向下转型,不安全的
System.out.println("i12="+i12);
C12 c122=new C12("hello");//向上转型,安全的
c122.print();
String i122=(String)c122.getObject();//向下转型,不安全的
System.out.println("i122="+i122);
CC<Integer> cc1=new CC<Integer>(1);
cc1.print();
int i3=cc1.getT();
System.out.println("i3="+i3);
CC<String> cc2=new CC<String>("我是用泛型定义的String类型的");
cc2.print();
String s3=cc2.getT();
System.out.println("s3="+s3);
}
}
效果
很明显,没有强转,也没有冗余的方法,这在我们做项目开发的时候,各种对象的创建就简单多了。
限制泛型类型限制类型?对,限制!
五个类,一个动物父类,两个动物子类,分别是猫狗,一个泛型T类型的Demo类,一个Test测试类。
Animal类的代码
package Java泛型02;
public class Animal {
public void print(){
System.out.println("我是一只动物");
}
}
Cat类的代码
package Java泛型02;
public class Cat extends Animal{
public void print(){
System.out.println("我是一只猫");
}
}
Dog类的代码
package Java泛型02;
public class Dog extends Animal{
//重写方法
public void print(){
System.out.println("我是一只狗");
}
}
Demo类代码
package Java泛型02;
//限制这个T类型是Animal的子类
public class Demo<T extends Animal> {
private T t;
public Demo(T t) {
super();
this.t = t;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public void print(){
System.out.println("T的类型是:"+t.getClass().getName());
}
}
Test类代码
package Java泛型02;
public class Test {
public static void main(String[] args) {
Demo<Dog> demo=new Demo<Dog>(new Dog());//传入的是一个Dog对象
Dog dog=demo.getT();
dog.print();
Demo<Cat> demo1=new Demo<Cat>(new Cat());//传入的是一个Dog对象
Cat cat=demo1.getT();
cat.print();
//这里定义Animal类型的也是可以的,重写一下Animal的构造方法就行了
//但是,下面这个就报错了,因为Integer不是Animal的子类
Demo<Integer> demo2=new Demo<Integer>(1);
}
}
效果图
把报错的注释掉再运行
很显然,这里的泛型的类型被限制了,这样可以有效的提高这个泛型的安全性。
通配符泛型通配符是什么东东?
通配符泛型在使用泛型的特殊的场景下用到,比如把泛型对象作为参数传入方法的时候,就用通配符泛型。
写一个新的测试类,定义一个方法,可以看到,我们的Dog类型的数据是没法调用Animal类型的数据的,同理,Cat也是不行的。
现在把Animal换成Dog,看看效果,Dog确实可以了,但是Cat是不行的
怎么解决这个问题呢?现在就要引入通配符了,把那个方法中的对象类型换成问号,这样就能解决这些问题了!
完整代码如下,不会创建的看我左边的位置创建的东西
Test代码
package Java泛型03;
import Java泛型02.Cat;
import Java泛型02.Demo;
import Java泛型02.Dog;
public class Test {
//写一个把前面的动物带走的方法
public static void take(Demo<?> a){
a.print();
}
public static void main(String[] args) {
Demo<Dog> demo=new Demo<Dog>(new Dog());
take(demo);
Demo<Cat> demo1=new Demo<Cat>(new Cat());
take(demo1);
}
}
泛型方法方法?函数方法
泛型方法指返回值和参数都用泛型表示的方法
Test代码
package Java泛型04;
/**
* 泛型方法
* @author Administrator
*
*/
public class Test {
public static <T> void f(T t){
System.out.println("T的类型是:"+t.getClass().getName());
}
public static void main(String[] args) {
f("");
f(1);
f(1.0f);
f(new Object());
}
}
效果图
泛型的基础差不多就学完了,后面自己用的时候,我习惯的不太熟的还是看java的帮助文档,把泛型引入到项目中去,实践才是硬道理。