java编程思想阅读笔记(八)泛型

    继续我的缓慢阅读,感觉细的东西真的是很多很多,往往在需要的时候才显得那么重要,所以让这种阅读算是有个印象,需要的时候能想起来,或者说脑子里有了那么个观念,熟能生巧是弥补的方式,可......好了,开始了:这次是泛型,优势有,局限也有(擦除),但是我还没有很深的感受到擦除的局限。
    泛型:适用于许多的类型,正如我们看到的容器类型,可以保存多种类型的对象,实现了“参数化类型”的概念;自己通俗的理解就是有那么一些代码,都是通用的,但是操作的对象呢,对类型没有特别的要求,那么我在用这些代码的时候再告诉它类型(参数化类型,告诉的类型就像传进去的参数,应该是这么个意思吧O(∩_∩)O~),这种方式可以用在类,也可以用在方法上。在类上使用,我们见到的比较多,示例都是的,我们在声明一个这样的类的时候就是在类名后使用<T>这种形式,当然可以不止一个参数,而且用容器的时候经常一个ArryList<Person> 声明一个可以保存Person类型对象的List;后面的示例会有。那么在接口和方法中使用呢,下面细看:
   (1)泛型应用于接口
    书中采用了一个Generator接口的示例,声明如下:
    public interface Generator<T> {T next();}
    这样确保其中的next方法返回值是参数的类型,使得next()的代码泛化。
   (2)泛型方法
    先看下语法:

    public<T> void f(T x){},将泛型参数列表置于返回值之前,看个示例:

package com.test.myjava;


public class GenericMethods{
	public <T> void f(T x){
		
		System.out.println(x.getClass().getName());
		
	}
	public <T extends FirstClass> void f1(T x){
		//T a = new T() ;无法编译通过,本身并不知道T的具体类型信息,即使在运行时已知
		T f1a = (T) new FirstClass();//居然可以通过,但是似乎没什么用
		//还没找到好的局限例子,现在只知道书中的容器对象通过.getClass().getTypeParameters()方法
		//可以获得泛型声明的类型参数,用这个方法试了一下main中的b,返回的也就是[T],但不是想要的
		
		x.funA();
		System.out.println("x:" + x.getClass().getName());
		System.out.println("f1a:" + f1a.getClass().getName());
		f1a.funA();
	}
	public static void main(String[] args) {
		GenericMethods gm = new GenericMethods();
		FirstClass fa = new FirstClass();
		SecondClass a = new SecondClass();
		ThirdClass<SecondClass> b = new ThirdClass(a);
		//显示对象自身类型
		gm.f("");
		gm.f(1);
		gm.f(1.0);
		gm.f('c');
		gm.f(gm);
		System.out.println();
		gm.f1(a);
		System.out.println("b:" + b.genericMember.getClass().getName());
		//从用对象获取类型看,没什么问题。
	}
}
class FirstClass{
	public void funA(){System.out.println("BasicClass.funA()");};
}
class SecondClass extends FirstClass{
	public void funB(){System.out.println("SecondClass.funB()");};
}
class ThirdClass<T> extends FirstClass{
	T genericMember;//可以编译
	ThirdClass(T x){
		genericMember = x;
		
	}
	public void funC(){System.out.println("ThirdClass.funC()");};
}

输出:

java.lang.String
java.lang.Integer
java.lang.Double
java.lang.Character
com.test.myjava.GenericMethods

BasicClass.funA()
x:com.test.myjava.SecondClass
f1a:com.test.myjava.FirstClass
BasicClass.funA()
b:com.test.myjava.SecondClass

   后面再用上擦除的概念,看看局限在哪里。

   (3)泛型方法与可变参数的使用:
    public static <T> List<T> makeList(T...args){
        List<T> result = new ArrayList<T>();
        for(T item : args)
          result.add(item);
        return result;
    }
   (4)擦除和边界
    由于早期的Java版本中是不支持泛型的,因此,在后来具有泛型功能,就要兼容前面的版本,所以有了其局限性;在Java泛型代码内部,是无法获得有关类型参数类型的信息的,因此不能将泛型类型显示地使用其运行时类型操作,如转型(本来就没什么作用),instanceof操作和new操作等,从前面的示例也可以看到。那么擦除又是个什么概念呢?按我的说法就是把类型参数替换为第一个非泛型类型,书上说的就是擦除到它的第一个边界(可能会有多个边界)。那边界的理解,书中说是对象进入和离开方法的地点,我是没有通俗的理解。那么在Java泛型具有擦除的性质下,有什么办法弥补呢,可以用类型标签(就是类型.class)把实际的类型信息告知,或者使用extends关键字,配合通配符“?”来弥补一些(这就是我们看到的<? extends >)。
   (5)潜在类型机制
    在书中还提到了这个概念,虽然说Java是不支持的,但是还是很有意义(c++支持),是只要实现某个方法子集,而不是某个特定类或接口,从而可以产生更加泛化的代码,因此可以横跨类继承结构,调用不属于某个公共接口的方法。
    看来很多c++拥有的特性都被Java删除了,难怪说Java是简化了c++而演化了的,当时以为就是个指针、模板之类的变化了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值