Java反射机制学习

来源:互联网 发布:linux awk 函数 编辑:程序博客网 时间:2024/05/21 17:06

Java反射机制学习

一、定义

反射机制是在运行状态中,对于任意一个类,都能获取这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。

二、用途

  • 运行时获取任意一个对象所属的类;
  • 运行时动态生成任意一个类的对象;
  • 运行时获取任意一个类所具有的字段和方法;
  • 运行时动态调用任意一个对象的方法;
  • 运行时获取注解信息;
  • 生成动态代理

三、具体功能实现

1、准备工作

为了更好的介绍反射机制功能的实现,我们先定义了一些类作为分析对象,利用它们进行更好的说明,如下:

首先,是我们自己定义了一些注解:

//用于注解类@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface ClassAnno {}//用于注解变量@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface FieldAnno {    String name() default "sfw";}//用于注解方法@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface MethodAnno {}//用于注解方法的参数@Target(ElementType.PARAMETER)@Retention(RetentionPolicy.RUNTIME)public @interface ParaAnno {}//用于注解方法的d参数@Target(ElementType.PARAMETER)@Retention(RetentionPolicy.RUNTIME)public @interface ParaAnno {}

然后,定义了一些类,用于说明反射机制。

interface Animal {}class Person implements Animal {    private String address;    public String getAddress() {        return address;    }    public void setAddress(String address) {        this.address = address;    }}@ClassAnnoclass Student extends Person {    @FieldAnno    public String name;    @FieldAnno    private int age;    public Student() {    }    public Student(String name, int age) {        this.name = name;        this.age = age;    }    @MethodAnno    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @MethodAnno    public void setNameAndAge(@ParaAnno @ParaAnno2 String name, @ParaAnno @ParaAnno2 int age) {        this.setName(name);        this.setAge(age);    }    private void ceshi(){        System.out.println("private方法调用");    }}

好了,接下来正式进行反射机制的分析:

2、获取Class对象

在反射中,常用的获取Class对象的方法有三种

(1) 通过类的对象调用getClass()方法的方式:

Class pClass1 = person.getClass();

(2) 通过Class类的静态方法forName():

Class pClass2 = null;pClass2 = Class.forName("com.sfw.anno.reflectiondemo.Person");

注:forName方法的参数必须为完全限定类名(包名+类名)。

(3) 通过类字面常量获得:

Class pClass3 = Person.class;

类字面常量不仅可以应用于普通的类、接口、数组、基本数据类型。

(4) 基本数据类型也可以通过TYPE字段获得:

Class longClass2 = Long.TYPE;

Java中常用的基本数据类型和TYPE的对应关系:

基本数据类型 TYPE boolean Boolean.TYPE char Character.TYPE short Short.TYPE int Integer.TYPE long Long.TYPE float Float.TYPE double Double.TYPE void Void.TYPE

3、通过Class对象获取类名

常用的有两个方法:

方法 作用 示例 getName() 获取完全限定类名 String personName = pClass1.getName(); getSimpleName() 仅获取类名,不包含包名 String personName = pClass1.getSimpleName();

4、通过Class对象获取类修饰符

获取类的public、private、static等修饰符的方法:

int modifiers = pClass1.getModifiers();

getModifiers()方法的返回值是int类型,每种修饰符就是这个返回值的其中一位,如果对应位为1,则表示这个类包含这个修饰符。

常用修饰符、对应位、修饰符是否使用方法对应关系如下:

修饰符 对应位 判断方法 public 0x00000001 Modifier.isPublic(modifiers) private 0x00000002 Modifier.isPrivate(modifiers) protected 0x00000004 Modifier.isProtected(modifiers) static 0x00000008 Modifier.isStatic(modifiers) final 0x00000010 Modifier.isFinal(modifiers) synchronized 0x00000020 Modifier.isSynchronized(modifiers) volatile 0x00000040 Modifier.isVolatile(modifiers) transient 0x00000080 Modifier.isTransient(modifiers) native 0x00000100 Modifier.isNative(modifiers) interface 0x00000200 Modifier.isInterface(modifiers) abstract 0x00000400 Modifier.isAbstract(modifiers) strict 0x00000800 Modifier.isStrict(modifiers)

5、通过Class对象获取类的包信息

通过getPackage()方法获取指定类的包信息:

Package pkg = pClass1.getPackage();String packageName = pkg.getName();

6、通过Class对象获取父类

通过getSuperclass()方法获取指定类的的父类:

Class studentClass = Student.class;Class superStudentClass = studentClass.getSuperclass();

7、通过Class对象获取类实现的接口

getInterfaces()方法获取类实现的接口,返回值是一个Class数组,即类可能实现多个接口。

Class[] interfaces1 = pClass1.getInterfaces();Class[] interfaces2 = studentClass.getSuperclass().getInterfaces();

8、通过Class对象获取类构造器生成实例

  • 获取类无参数构造器并生成实例:
Constructor constructor1 = studentClass.getConstructor();Student student1 = (Student) constructor1.newInstance();
  • 获取类有参数构造器并生成实例:
Constructor constructor2 = studentClass.getConstructor(String.class, int.class);Student student2 = (Student) constructor2.newInstance("sfw", 27);

9、通过Class对象获取类的方法

获取所有public方法,包括子类和父类的public方法:

Method[] methods1 = studentClass.getMethods();

获取指定的public方法:

Method method1 = studentClass.getMethod("setAddress", String.class);

调用参数为空的public方法:

Method getage = student2.getClass().getMethod("getAge");int age = (int) getage.invoke(student2);

调用多参数的public方法:

Method setNameAndAge = student2.getClass().getMethod("setNameAndAge", String.class, int.class);setNameAndAge.invoke(student2, "wsf", 18);

获取方法的参数类型

Class[] paraTypes = setNameAndAge.getParameterTypes();

获取本类所有方法

Method[] declaredMethods = student2.getClass().getDeclaredMethods();

调用本类方法,如果方法为private,需要调用setAccessible(true)后,才能调用。

Method ceshi =student2.getClass().getDeclaredMethod("ceshi");ceshi.setAccessible(true);ceshi.invoke(student2);

10、变量

获取所有public变量,包括本类和父类的public变量:

Field [] fields = student2.getClass().getFields();

获取指定public变量,并设置变量值,读取变量值:

Field field = student2.getClass().getField("name");field.set(student2,"shufengwu");String name = field.get(student2);

获取本类变量,包括私有变量,访问私有变量调用setAccessible(true):

Field[] declaredFields = student2.getClass().getDeclaredFields();for (Field declaredField:declaredFields){    field.setAccessible(true);    System.out.println(declaredField.getName());}

获取本类指定变量:

Field declaredField = student2.getClass().getDeclaredFields("age");

11、获取注解

获取类上注解:

Annotation [] annotations = Student.class.getAnnotations();

获取类上指定注解:

ClassAnno classAnno = Student.class.getAnnotation(ClassAnno.class);

获取指定字段上指定注解及参数值:

FieldAnno fieldAnno = Student.class.getField("name").getAnnotation(FieldAnno.class);System.out.println(fieldAnno +" "+ fieldAnno.name());     

获取指定方法的注解:

Method method = Student.class.getMethod("setNameAndAge",String.class,int.class);MethodAnno methodAnno = method.getAnnotation(MethodAnno.class);System.out.println(methodAnno);

获取指定方法的参数的注解:

Method method = Student.class.getMethod("setNameAndAge",String.class,int.class);//一个方法可能有多个参数,一个参数可能有多个注解Annotation[][] parameterAnnotations = method.getParameterAnnotations();//遍历每个参数for (int i=0;i<parameterAnnotations.length;i++){    Annotation[] annotations2 = parameterAnnotations[i];    //遍历参数的每个注解    for (int j = 0;j<annotations2.length;j++){          System.out.print(annotations2[j]+" ");    }    System.out.println();}

点击此处获取使用例程

参考文献

【1】 Java反射机制详解
http://baike.xsoftlab.net/view/209.html#1

【2】 Java反射详解
http://blog.csdn.net/a15286856575/article/details/53330821?locationNum=1&fps=1

0 0
原创粉丝点击