限制泛型可用类型,类型通配符声明,泛型方法

一、限制泛型可用类型

①   在定义泛型类型时,默认在实例化泛型类的时候可以使用任何类型,但是如果想要限制使用泛型类型时,只能用某个特定类型或者是其子类型才能实例化该类型时,可以在定义类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个类;

②   当没有指定泛型继承的类型或接口时,默认使用extends Object,所以默认情况下任何类型都可以作为参数传入;

继承抽象类

 1 public class GenericDemo3{
 2     public static void main(String []args){
 3         GenericClass<Dog> dogClass=new GenericClass<Dog>();
 4         dogClass.setObj(new Dog());
 5         dogClass.getObj().eat();
 6
 7
 8         GenericClass<Cat> catClass=new GenericClass<Cat>();
 9         catClass.setObj(new Cat());
10         catClass.getObj().eat();
11     }
12 }
13
14 //泛型类所接受的参数做了限制,只能接收Animal类型或者Animal类的子类
15 class GenericClass<T extends Animal>{
16     private T obj;
17     public void setObj(T obj){
18         this.obj=obj;
19     }
20     public T getObj(){
21         return obj;
22     }
23 }
24
25 abstract class Animal{
26     public abstract void eat();
27 }
28
29 class Dog extends Animal{
30     public void eat(){
31         System.out.println("啃骨头");
32     }
33 }
34 class Cat extends Animal{
35     public void eat(){
36         System.out.println("吃鱼肉");
37     }
38 }

继承接口

 1 public class GenericDemo3{
 2     public static void main(String []args){
 3         GenericClass<Dog> dogClass=new GenericClass<Dog>();
 4         dogClass.setObj(new Dog());
 5         dogClass.getObj().eat2();
 6
 7
 8         GenericClass<Cat> catClass=new GenericClass<Cat>();
 9         catClass.setObj(new Cat());
10         catClass.getObj().eat2();
11     }
12 }
13
14 //泛型类所接受的参数做了限制,只能接收Animal类型或者Animal类的子类
15 class GenericClass<T extends Animal2>{
16     private T obj;
17     public void setObj(T obj){
18         this.obj=obj;
19     }
20     public T getObj(){
21         return obj;
22     }
23 }
24
25 interface Animal2{
26     public abstract void eat2();
27 }
28
29 class Dog implements Animal2{
30     public void eat2(){
31         System.out.println("啃骨头2");
32     }
33 }
34 class Cat implements Animal2{
35     public void eat2(){
36         System.out.println("吃鱼肉2");
37     }
38 }

二、类型通配符声明

①   同一泛型类,如果实例化时给定的实际类型不同,则这些实例的类型是不兼容的,不能相互赋值;

Generic<Boolean> f1=new Generic<Boolean>();

Generic<Integer> f2=new Generic<Integer>();

f1=f2;//发生编译错误

Generic<Object> f=f1;//f1和f类型并不兼容,发生编译错误

f=f2;//f2和f类型同样不兼容,也会发生编译错误

②   泛型类实例之间的不兼容性会带来使用的不便。我们可以使用泛型通配符(?)声明泛型类的变量就可以解决这个问题;

③   泛型通配符的方式

“?”代表任意一个类型;

Generic<Boolean> f1=new Generic<Boolean>();

Generic<?> f=f1;

和限制泛型的上限相似,同样可以使用extends关键字限定通配符匹配类型的上限;

Generic<Dog> f1=new Generic<Dog>();

Generic<? extends Animal> f=f1;

还可以使用super关键字将通配符类型限定为某个类型及其父类型;

Generic<Animal> f1=new Generic<Animal>();

Generic<? super Dog> f=f1;

 1 public class GenericDemo4{
 2     public static void main(String []args){
 3         GenericClass<Dog> dogClass=new GenericClass<Dog>();
 4         dogClass.setObj(new Dog());
 5         dogClass.getObj().eat();
 6
 7         GenericClass<Cat> catClass=new GenericClass<Cat>();
 8         catClass.setObj(new Cat());
 9         catClass.getObj().eat();
10
11         GenericClass<String> StringClass=new GenericClass<String>();
12
13         //dogClass=catClass;//编译出错
14
15         //无限定通配符的使用
16         GenericClass<?> gClass=null;
17         gClass=dogClass;
18         ((Dog)gClass.getObj()).eat();//因父类为object类型,所以要强制转换
19
20         gClass=StringClass;
21
22         //上边界限定通配符
23         GenericClass<? extends Animal> subclass=null;
24         subclass=dogClass; //Animal a=dog;
25         subclass.getObj().eat();
26
27         //下边界限定通配符
28         GenericClass<? super Dog> sclass=null;
29         GenericClass<Animal> cClass=new GenericClass<Animal>();
30         //sclass=catClass; //编译错误,类型不兼容
31         sclass=cClass;//可以通过编译
32     }
33 }
34
35
36 class GenericClass<T>{
37     private T obj;
38     public void setObj(T obj){
39         this.obj=obj;
40     }
41     public T getObj(){
42         return obj;
43     }
44 }
45
46 interface Animal{
47     public abstract void eat();
48 }
49
50 class Dog implements Animal{
51     public void eat(){
52         System.out.println("啃骨头");
53     }
54 }
55 class Cat implements Animal{
56     public void eat(){
57         System.out.println("吃鱼肉");
58     }
59 }

三、泛型方法

①   不仅类可以声明泛型,类中的方法也可以声明仅用于自身的泛型,这种方法叫做泛型方法。其定义格式为:

访问修饰符<泛型列表> 返回类型 方法名(参数列表){

实现代码

}

②   在泛型列表中声明的泛型,可用于该方法的返回类型声明、参数类型声明和方法代码中的局部变量的类型声明;

③   类中其它方法不能使用当前方法声明的泛型;

注:是否拥有泛型方法,与其所在的类是否泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前;

④   什么时候使用 泛型方法,而不是泛型类?

添加类型约束只作用于一个方法的多个参数之间,而不涉及到类中的其它方法;

施加类型约束的方法为静态方法,只能将其定义为泛型方法,因为静态方法不能使用其所在类的类型参数;

 1 public class GenericDemo5{
 2     public static void main(String []args){
 3         GenericClass2 gen=new GenericClass2();
 4         gen.println("abc");
 5         gen.println(true);
 6         gen.println(10);
 7         gen.println(10.5);
 8         gen.println(new Dog());
 9         gen.println(new Cat());
10         GenericClass2.print("哈哈");
11     }
12 }
13
14 class GenericClass2{
15     //泛型方法
16     public <T> void println(T content){
17         System.out.println(content);
18     }
19     //泛型方法的重载
20     public <T extends Animal> void println(T animal){
21         animal.eat();
22     }
23
24     public static <T> void print(T content){
25         System.out.println(content);
26     }
27 }
28
29 interface Animal{
30     public abstract void eat();
31 }
32
33 class Dog implements Animal{
34     public void eat(){
35         System.out.println("啃骨头");
36     }
37 }
38 class Cat implements Animal{
39     public void eat(){
40         System.out.println("吃鱼肉");
41     }
42 }
时间: 2024-12-29 11:08:42

限制泛型可用类型,类型通配符声明,泛型方法的相关文章

泛型中的类型约束和类型推断

前一篇文章介绍了泛型的基本概念.在本文中,我们看一下泛型中两个很重要的特性:类型约束和类型推断. 类型约束 相信你还记得前面一篇文章中的泛型方法,在这个泛型方法中,我们就使用了类型约束. 类型约束(type constraint)进一步控制了可指定的类型实参,当我们创建自己的泛型类型或者泛型方法的时候,类型约束是很有用的. 回到前一篇例子中的泛型方法,这个泛型方法就要求可指定的类型实参必须实现了IComparable接口. 为什么会有这个约束呢?原因很简单,因为我们在泛型方法的实现中直接调用T类

黑马程序员 - 泛型和基本类型包装类

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 泛型好处:1.将运行时期的ClassCastException,转移到了编译时期 方便程序员解决问题,让运行时期问题减少. 2.避免了强制转换.泛型格式:通过<>来定义要操作的引用数据类型.通常在集合框架中很常用.泛型类:当类中需要操作的引用数据类型不确定的时候,早期用Object来实现扩展.现在运用泛型类. 当方法中需要操作的引用数据类型不确定的时候,可以运用泛型方法.特殊之处:静态方法,

Gson通过借助TypeToken获取泛型参数的类型的方法(转)

最近在使用Google的Gson包进行Json和Java对象之间的转化,对于包含泛型的类的序列化和反序列化Gson也提供了很好的支持,感觉有点意思,就花时间研究了一下. 由于Java泛型的实现机制,使用了泛型的代码在运行期间相关的泛型参数的类型会被擦除,我们无法在运行期间获知泛型参数的具体类型(所有的泛型类型在运行时都是Object类型). 但是有的时候,我们确实需要获知泛型参数的类型,比如将使用了泛型的Java代码序列化或者反序列化的时候,这个时候问题就变得比较棘手. class Foo<T>

泛型T的类型获取

T.getClass()或者T.class都是非法的,因为T是泛型变量. 由于一个类的类型是什么是在编译期处理的,故不能在运行时直接在Base里得到T的实际类型. /** * 可以在service层直接调用,也可以在DAO层扩展调用 */ public class BaseDaoImpl<T> implements BaseDao<T> private Class<T> persistentClass; /** * 用于Dao层子类使用的构造函数. 通过子类的泛型定义取

Gson通过借助TypeToken获取泛型参数的类型的方法

最近在使用Google的Gson包进行Json和Java对象之间的转化,对于包含泛型的类的序列化和反序列化Gson也提供了很好的支持,感觉有点意思,就花时间研究了一下. 由于Java泛型的实现机制,使用了泛型的代码在运行期间相关的泛型参数的类型会被擦除,我们无法在运行期间获知泛型参数的具体类型(所有的泛型类型在运行时都是Object类型). 但是有的时候,我们确实需要获知泛型参数的类型,比如将使用了泛型的Java代码序列化或者反序列化的时候,这个时候问题就变得比较棘手. class Foo<T>

Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除的问题解决

在开发时,遇到了下面这条语句,不懂,然习之. private List<MyZhuiHaoDetailModel> listLottery = new ArrayList<MyZhuiHaoDetailModel>(); Gson gson=new Gson(); JSONObject object=new JSONObject(callbackValue); listLottery =  gson.fromJson(object.getString("lists&quo

java获取泛型的实际类型

这是一个困扰了我好久的问题,在我写的android请求框架总结(二)中写到过利用框架自动解析json数据,代码如下 Object o; if (result.charAt(0) == '{') { //解析对象 o = new Gson().fromJson(result, clazz); } else { //这个方法是在stackoverflow中找到的可将json转换为list,普通的通过type去解析是不行的 o = new Gson().fromJson(result, com.goo

Java进阶 四 Java反射TypeToken解决泛型运行时类型擦除问题

在开发时,遇到了下面这条语句,不懂,然习之. private List<MyZhuiHaoDetailModel> listLottery = new ArrayList<MyZhuiHaoDetailModel>(); Gson gson=new Gson(); JSONObject object=new JSONObject(callbackValue); listLottery =  gson.fromJson(object.getString("lists&quo

泛型中的类型擦除

通过反射理解泛型的本质(类型擦除) Java中的泛型是通过类型擦除来实现的.所谓类型擦除,是指通过类型参数合并,将泛型类型实例关联到同一份字节码上.编译器只为泛型类型生成一份字节码,并将其实例关联到这份字节码上.类型擦除的关键在于从泛型类型中清除类型参数的相关信息,并且再必要的时候添加类型检查和类型转换的方法. 下面通过两个例子来证明在编译时确实发生了类型擦除. 例1分别创建实际类型为String和Integer的ArrayList对象,通过getClass()方法获取两个实例的类,最后判断这个