本帖最后由 程传鹏 于 2011-12-19 07:17 编辑
楼主,给你发下我的这几节内容的学习日记,请认真看完,看完你就应该知道为什么了(本人博客地址:http://blog.sina.com.cn/u/2286901677,欢迎各位同学来交流)
7. 反射
Class代表一个类,java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则是由这个类的实例对象来确定,不同的实例对象有不同的属性值,java程序中的各个java类,他们也属于同一类事物,是可以用一个类描述的事物,这个类的名字就是Class,它描述了类的名字,类的访问属性,类所属包的名字,字段名称的列表,方法名称和列表,学习反射,首先要明白Class这个类
字节码:类在硬盘上加载到内存上的编码
反射:反射就是把java类中各种成分映射成相应的java类
Constructor:返回字节码中的构造方法,获得方法时要用到类型。
Field类:返回类中的一个成员变量
Method类:返回类中的某一个成员方法
反射的作用:实现框架的功能
10.泛型
泛型:没有使用泛型时,只要是对象,不管是什么类型的对象,都可以存储同一个集合中,使用泛型集合,可以将一个集合中的元素限定为一个特定类型,集合中只能存储同一个类型的对象,这样更安全,并且当从集合中获取一个对象时,编译器也可以知道这个对象的类型,不需要对对象进行强制类型转换,这样更方便。泛型是给编译器看的,其他类型的数据也可以存入与自己不同类型的集合中,但编译不通过,但可以通过反射做到。
泛型中的术语
ArrayList<E>泛型类型,E称为类型变量或类型参数。ArrayList<Integer>称为参数化了的类型,其中的Integer称为类型参数的实例或实际类型参数。<>读做typeof.ArrayList称为原始类型
参数化类型与原始类型的兼容性
1.参数化类型可以引用一个原始类型的对旬,编译报告警告,如
Collection<String> c=new Vector();
2.原始类型可以引用一个参数化的类型的对象,编译报告警告,如
Collection c=new Vector<String>();
参数化类型不考虑类型参数的继承关系,如
Vector<String> v=new Vector<Object>();//这是错误的
Vector<Object> v=new Vecotr<String>();//这也是错误的
在创建数组实例时,数组的元素不能使用参数化类型,如
Vector<Integer> c[]=new Vector[10];这是错误的
11.泛型中的通配符 ?
使用?通配符可以引用其他各种参数化类型,可以引用其他各种参数化类型,?通配符定义的变量主要用作引用,可以高调用与参数化无关的方法,不能调用与参数化有关的方法,?通配符的扩展,Collection<? extends Number>x=new Collection,其中extends是限定通配符,用来限定x是Number或Number的子类,限定通配符总是包括自己,也可以用super限定符,表示父类
Map没有实现Itreble接口,不能进行直接迭代,可以由set实现
12.自定义泛型
private static int add(int x,int y){return x+y}
private static <T> T add(T x,T y){return null}泛型定义方法
调用时,add(3,5),add(3.5,3),add(3,"abc")
第一个,3 int类型的,5 int 取交集的最小值,即int,结果为 int add();
第二个,3.5 double,3 int 交集的最小值为Number,Number add();
同理,第三个,为Object add();
交换数组中两个元素的位置(数组类型不确定)
泛型定义方法
private static <T> void swap(T[],int i,int j){T temp=a;a=a[j];a[j]=tem}
其中T即泛型的类型,只能是对象或引用类型,不能是基本类型,我们可以用swap(String,3,5),但是不能
使用swap(int[],3,5),
注意:只有引用类型才能作为泛型方法的实际参数,对于add方法,使用基本类型的数据进行测试没有问题,这是因为自动装箱和拆箱原理,而swap(int[],3,5)语句会报编译错误,这是因为器不会对new int[]中的int自动装箱和拆箱,因为new int[]本身已经是对象了,你想要的有可能就是这个数组本身,给它装箱就弄巧成拙了。
13.在定义泛型时,也可以用extends限定符
14.参数的类型推断
编译器判断泛型方法的实际类型参数的过程称为类型推断
类型推断相对于知觉推断的,其实现方法是一种非常复杂的过程,根据调用泛型方法时,实际传递的参数类型或返回值类型来推断,具体规则如下:
1.当某个类型变量只在整个参数列表中的所有参数和返回值中的一处被应用了,那么根据调用方法时该处的实际应用类型来确定,这很容易凭着感觉推断出来,即直接根据调用方法时传递的参数类型或返回值类型来决定泛型参数的类型,如:swap(new String[3],3,,4)--->static <T>void swap(T[],int i,int j)
2.当某个类型变量只在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时,这多处的实际应用类型都对应同一种类型来确定,这很容易,凭着感觉推断出来,如:
add(3,5)--->static<T>T add(T a,T b)
3.当某个类型变量只在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时,这多处的实际应用类型都对应到了不同的类型,并且没有使用返回值,这时候取多个参数中的类型的交集的最小值,如:
fill(new Integer[3],3,5f)---->static <T> void fill(T[],T a,T b)
4.当某个类型变量只在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时,这多处的实际应用类型都对应到了不同的类型,并且返回值,这时候优先考虑返回值的类型,如下面的语句对应的类型就是Integer了,编译将报告错误,将变量x的类型改为float,对比eclipse中的错误提示,接着再将其改为Number类型,则没了错误。
int x=(3,3.5f)--->static <T>T add (T a,T b)
5.参数类型的类型推断具有传递性。下面第一种情况推断实际参数类型为Object,编译没有问题,而第二种情况则根据参数化的Vector类实例将类型变量直接确定为String类型,编译将出现问题:
copy(new Integer[5],new String[5])-->static <T> void copy(T[] a,T[] b);
copy(new Vector<String>().new Integer[5])-->static <T> void copy(Collection<T> a,t[] b); |