黑马程序员__泛型以及反射

 ------- android培训java培训、期待与您交流! ----------

泛型:
jdk1.5以后出现的新特性,用于解决安全问题。
因为集合当中可以添加各种类型数据,如果一开始指定了泛型,后期就不会再存入其他类型的数据。

ArrayList<String> al=new ArrayList<String>();

以上代码定义一个容器,只能存储String类型。

容器的迭代器也要申明泛型类型,此类型应与容器声明的泛型类型相同

Iterator<String> it=al.iterator();

泛型的好处总结:
(1)将运行时期出现的类型转换异常,转移到了编译时期,也就是说,存入不同类型时,编译失败。
(2)避免了强转的麻烦。

通常API中有<>的接口或者类时,就可以根据需要定义泛型。(不是必须的)。

泛型类:
当类中要操作的引用数据类型不确定时,
早期定义Object类利用多态性质来完成扩展,
现在定义泛型来完成扩展。

泛型类定义的泛型在整个类中有效,如果被方法使用。
那么泛型类的对象明确要操作的具体类型之后,所有要操作的类型已经固定了。
类上定义的泛型在方法中使用一般做为参数传递就行。
为了让不同的方法可以操作不同的类型,而且类型还不确定。
那么可以将泛型定义在方法上面。定义在方法上的泛型只会作用于这个方法本身。

可以既在类上定义泛型,又在类中的方法上定义不同的泛型。
静态的方法不能使用类上定义的泛型,如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上面。

public static<M>void show(M m)(注意泛型放在返回值修饰符的前面)

泛型可以定义在方法,类,接口以及容器上。
如果实现泛型接口的实现类没有指定泛型的类型就需要再次在类上面指定泛型,在容器上使用泛型时,如果泛型类型不明确,可以用<?>也可以指定为T,但是这样方法上必须指定T,而且在方法中可以对T进行操作。

public static void printcoll(ArrayList<?> al){
Iterator<?> it=al.iterator();

while(it.hasNext());{
system.out.println(it.next());
}
}
public static<T> vodi printcoll(ArrayList<T> al){
Iterator<T> it=al.iterator();

while(it.hasNext());{
T t=it.next();//对T进行了操作

}

容器中定义泛型时:
ArrayList<T> al=new ArrayList<T>();//左右两边要一致都是T。
泛型限定,指定泛型可以接收的范围
<?extends E>接收E类及其子类
<? super E>接收E类及其父类

 

反射的基石是--class类

1.java程序的各个java类属于同一类事物,描叙这类事物的java类名就是Class。
person p1=new person();
当我们用到了源程序中的person类中,需要首先将类的字节码从硬盘上加载到内存中,得到字节码的三种方法
(1)在源程序中直接用person.class 类名.class

p1.getclass();//得到该类的字节码。用实例得到

class.forName("...")//返回字节码。反射中用这种形式。...为类的全名

有9个基本的class字节码实例对象,就是八个基本类型加上一个void类型。
 例如得到一个对象的字节码的方法

String str1="abc"

Class cls1= str1.getClass();
Class cls2= String.class;
Class cls3=Class.forName("java.lang.String");

三种方式得到的都是相同的对象。
cls1.isPrimitive();//是否是一个基本类型,String不是,返回false.
注意:包装类中的比如说Integer中有一个TYPE常量,代表包装类所包装的类型的字节码,也就是Integer.TYPE等价于int类型的字节码。
int.class==Integer.TYPE
数组的类型不是原始类型。


反射:就是把java的一个类中得到每一个成分都映射相应的java类。


Constructor类
得到一个类中的所有的构造方法。
比如说得到一个String类的一个构造方法:
String.class.getConstructor(StringBuffer.class)表示找到那个带有Stringbuffer参数的构造函数。各个参数都需要用class来反射得到字节码,并且用逗号隔开。这样上述代码就得到了一个Constructor类。
这个类中有一些方法可以供我们使用。

Constructor ctr=String.class.getConstructor(StringBuffer.class)
ctr.newInstance(new StringBuffer("abc"));//用String的构造函数来实
现String类创造一个对象,实实在在的去用构造函数来实现。

这里ctr调用方法时会返回一个String类型对象,用一个String类型引用去接收时要注意必须对这个创建的实例对象进行强制类型转换,因为编译器不清楚到底会返回什么类型。编译器不会看运行后的类型,而只是看声明的类型。
String s=(String)ctr.newInstance(new StringBuffer("abc"));
总结一点,反射的应用就是两个步骤,(1)获得方法,(2)使用方法。

Field类

代表字节码中的某个变量。也就是类中的成员变量。
 Field getDeclaredField(String name) 得到不可见的成员变量类型。
参数代表调用这个方法的class对象中存在的成员变量名。
 Field getField(String name)  得到可见的成员变量类型。这个地方就必须要清楚name到底是什么。
注意Field为返回类型,而调用此方的调用者是字节码,也就是class对象。
Field类中方法
 Object get(Object obj)  其中的对象obj是该class的实例的一个引用。
如果此field是不公开的,还需调用以下方法:

 void setAccessible(boolean flag)设置此flag为true就可以。//注意此方法为Field继承自父类的一个静态方法。

再调用 field类的get方法即可。
 
Field.getType()方法返回的是字段类型的字节码如果是String类型,就相当于String.class.
field.set(obj,newValue)用新的值替代,这个obj是表示这个field所表示的字段所在的类。

Method类
可以先得到类中的一个方法,再通过方法根据对象使用该方法。
Method mt= String.class.getMethod("参数名字","写参数列表");注意参数列表都是用反射来表示的,比如说,原方法有个String类型参数,那么就得写String.class.
mt.invoke(具体对象(包含此方法的类型的对象),此方法需要的参数)
如果具体对象为null,那么意味着这个mt对应一个静态方法。
参数可以写成new Object[]{参数1,参数2,...},这里有一个问题是,如果此方法的参数是一个数组时,这里传入参数时,应该将这个数组也放到这个参数数组中,也就是数组中再放数组。也可以将这个数组前面加上一个(Object)告诉编译器这是一个数组参数,不能拆开。

int [] a=new int[3];
int [] a1=new int[4];
int[][] a2=new int[2][3]
String [] a3=new String[3];

a.getClass==a2.getClass();//比较结果为true.维度相同并且类型相同的数组的字节码才是相同的。
class的getName方法有规定打印的名字的规则。

class的getSuperclass();//返回该class的父类字节码。
class.isArray判断class对象是否是一个数组字节码类型。
注意一点,基本类型的数据不是Object类型。

Array类完成对数组的反射。
static Object get(Object array, int index) 根据指定索引返回对应值
static int getLength(Object array)  返回数组长度。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值