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