java之反射-注解

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

java中的类是用来描述一类事物的共性的。它确定了这类事物该有什么属性,没有什么属性,该有什么行为,没有什么行为。至于这个属性是什么,这个行为具体是什么则由这个类的实例所决定。那么类是用来描述一类事物的共性,那它本身也就是一类事物,在Java中用来描述类的类的名字叫做Class注意这个C是大写。

Class类的实例对象就是个各类在内存中的字节码。

如何得到各个字节码对应的实例对象?

1,类名.class 例如:System.class

2,对象.getClass() 例如: new Perosn().getClass();

3,Class.forName(类全名);例如:Class.forName("java.util.Date");

注意:forName()方法加载有两种情况:第一种这个类的字节码已经加载进了内存,它直接返回这个字节码的对象。第二种:这个类的字节码没有被加载过,会先让类加载器加载这个类到内存,然后返回这个字节码的对象。

Class中有九个预定义实例对象:其中八个基本类型实例对象(byte,short,int ,long,char,flot,double,boolean),一个void实例对象。

注意:只要在源程序中出现的类型,都有自己的Class实例对象。

int是种数据类型,而Interger是封装了该类型的封装类。char对应了Character,这些基本数据类型都有对应它们的封装类。这些封装类都有TYPE这个常量,对应它们的基本数据类型的字节码。

字节码之间的比较虽然用equals可以但是因为字节码只存在一份,所以最好用==比较。

int.class == Integer.TYPE  char.class ==Character.TYPE 

isPrimitive()判断是否是基本类型。isArray()判断是否是数组。

Constructor类是代表构造函数的:

Constructor getConstructor(类型.class);返回指定的public构造方法。其实这个方法中的参数就是,原构造函数中参数的类对象。

Constructor[] getConstructors();返回所有的public构造方法

得到了构造方法后:用Constructor的 newInstance();方法创建对象,返回的是Object类型的对象。如果返回的是有参的构造方法那么在newInstance()方法中就要指定你要传入的具体参数。

例如: String.class.getConstructor(SringBuilder.class).newInstance(new StringBuilder("哈哈"));

Class类中也有一个newInstance()方法,该方法的内部获取了无参的构造方法。所以当我们不需要通过有参的构造方法创建对象时要使用class类中的newInstance()方法。

Filed类是代表成员变量的:

我们可以通过Class类的

获取指定的并且public的Field对象。getField(变量名)//这个方法取出的是这个类中的变量,并不是某个对象的变量。我们可以通过获取到这个类的变量对象,在通过Field对象获取到

具体某个对象变量值。

获取所有的public的Field对象。getFields();

获取指定的Field对象。getDeclaredField()

获取所有的Field对象getDeclaredFields()

获取Field对象的类型。getType()

设置某个字段的值:set(obj,value);

当我们获取到这个Field对象后,通过Field对象的get(对象名)方法,来获取它所属对象后的值。

如果我们获取到的这个Field是私有的那么我们需要暴力的访问该成员变量。方法是Accessible(true);然后再通过Field的get(变量名)来获取它所属对象的具体值。

注意:这个成员变量不是指的某个对象的而是代表这个类的成员变量。

Method是用来描述方法的类。我们可以通过Class的getMethod等方法获取到该对象。在通过Method的invovk(对象,参数)方法来执行这个方法所属对象的这个方法。

通过反射创建一个Vector集合并存入元素:


如果第一个参数为null,则证明这个Method对象对应着一个静态的方法。

对于method的invoke()方法,在jdk1.5时为了兼容jsk1.4 ,对此方法中的如果要传入的是数组参数,那么就对这个数组进行解包,

例如:当我们调用invoke(null,new String[] {"12","sd"})时,就会先对这个字符串数组进行解包,解开后就变成了invoke(null,"12","sd")

因此参数列表就不再是一个字符串数组,而变成了两个字符串,因此程序会报错,因为我们调用的方法传入的只有一个字符串数组,现在变成两个字符串当然会报错。

解决方案:1 考虑到它会先解包,那么我们就先在外面打一个包,让他解包完以后还是一个包。 例如:invoke(null,new Object[]{ new String[] {"12","sd"}})

解决方案:2 为了避免进行解包,那么我们可以告诉系统,这就是一个元素,不是一个包。因此String[] 这个整体就是一个Object那么我们把它转变成Object

例如:invoke(null,(Object)new String[] {"12","sd"})

数组的反射:

只要它们的数据类型相同,并且维数相同,那么它们对应的字节码只有一个。例如int类型数组对应的字节码文件的名为[ I

char类型数组为: [ C

注意:基本数据类型不继承与Object 因此当使用Arrays.asList()时,将不会转换成功。

如果我们列出基本数据类型数组中的内容,可以使用Arrays.toString(arr);方法。

但是int[]数组却继承与Object所以二维数组可以使用该方法。

在底层为哈希表数据结构的集合中:注意如果重写了hashCode方法中使用了一个成员变量算哈希值,当我们存入了这个对象,但是稍后改变了这个成员变量的值,那么我们移除时将不能够移除,因为当移除的时候还是依照这这个对象的哈希值去找在集合中的对象,哈希值变了那么就找不到这个对象了,所以移除失败。这样容易造成内存泄露。

在java7中有个新特性,Map map=(name:"jian",value:21);

注解:是在JDL1.5出现的。

Annotation是一个接口,可以通过反射获取指定元素的Annotation对象,然后通过对象获取对象里的数据。

Annotation可以为类,方法,成员变量等设置元数据。Annotation不会影响程序代码的执行。

java中提供了四种Annotation的用法:

1,@Verride。 限定重写父类的方法,次用法可以指定下面的方法必须是重写父类的方法。

2,@Deprecated 。 已经过时,此方法可以表示出下面的类或方法是过时的,当使用这个类或方法时编译器将发出警告。

3,@Suppress Warnings。压制警告,放在类上就是压制整个类的警告,放在方法中就是压制整个方法的警告,例如:当我们在不使用集合时不用泛型编译器就会发出警告,但是当我们将这个用法方法这个类或者方法中,就会压制这个警告。

4,@Safe Varargs 次用法是jdk7新增的。

在java.lang.annotation包下提供了四中元Annotation都用于修饰其它的Annotation定义。

1,@Retention:用于指定这个Annotation定义的生命周期,也就是可以保留多长时间。

它里面包含了一个返回值类型:RetentionPolicy的value属性。

这个RetentionPolicy只能值下面三种值:RetentionPolicy.Class,将Annotation记录在class文件中,当运行时不在保留。RetentionPolicy.RUNTIME,将Annotation保留到运行时,该程序可以通过反射获取该Annotation的信息。

RetentionPolicy.SOURCE。这个Annotation只会保留在源代码中。

2,@Target也只能修饰Annotation定义。它可以指定被修饰的Annotation可以修饰那些程序单元。

它的内部也只有一个value的属性。它的值有如下几个:

ElementType.ANNOTATION_TYPE:指定被修饰的Annotation只能修饰Annotation

ElementType.CONSTRUCTOR:指定被修饰的Annotation只能修饰构造函数

ElementType.METHOD:指定被修饰的Annotation只能修饰方法

ElementType.FIELD:指定被修饰的Annotation只能修饰成员变量

ElementType.TYPE:指定被修饰的Annotation可以修饰类,接口,Annotation,或者枚举定义。

ElementType.PARAMETER:指定被修饰的Annotation可以修饰参数。

ElementType.PACKAGE:指定被修饰的Annotation只嗯呢该修饰包。

ElementType.LOCAT_VARIABLE:指定被修饰的Annotation只能修饰局部变量。

3,@Documented能够指定被修饰的Annotation被一个程序使用后,可以被javadoc工具所提取。

例如:

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

@Documented

public @interface myAnnotation{

}

public class test{

@myAnnotation

public void showDocumented(){

}

}

如果此例子用javadoc提取的API文档在方法上面同样会出现这个Annotation

4,@Inherited:可以指定被修饰的Annotation具有继承性。

也就是 用@Inherited修饰 Annotation 的定义A 。那么一个类B使用了A,当另一个类C,继承了类B,那么这个类C自动用A修饰。

当自定义时,Annotation定义里如果只有一个属性value 那么在使用该Annotation时可以直接赋值,如果不只有一个属性,那么可以给除了value以外的属性,设置缺省值。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值