java中的反射详解

来源:互联网 发布:巨化集团待遇知乎 编辑:程序博客网 时间:2024/05/18 01:28

反射

前段时间,网易面试,面试官问我关于反射方面的知识,回答的不是特别好,今天特此补充学习一下~~~

简介

反射是java语言被视为动态或者准动态语言的一个关键性质,这个机制允许程序在运行时通过Reflection API获取任何一个已知名称的class的内部信息,包括修饰符(public static等)、字段或者方法的所有信息、父类以及实现的接口,并可在运行时改变字段的内容或者调用方法。
简单的说,反射机制可以在运行时动态的获取任意一个类的属性和方法,并可以对任意一个属性进行赋值,调用任意一个方法。(即便是私有方法,只要设置setAccessible)

Jdk中的Reflection API

这里写图片描述

Java反射案例

在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判段任意一个类所具有的成员变量和方法
在运行时调用任一个对象的任意一个方法和属性

在使用java反射功能时,首先要获取该类的Class对象,再通过Class对象获取其他对象。

1 获取Class对象

Student s = new Student();//获取Class对象//1 getClass方法Class<?> clazz1 = s.getClass();System.out.println(clazz1); //class com.wy.reflect.Student//2 .class语法System.out.println(Student.class); //class com.wy.reflect.Student//3 Class.forName()Class<?> clazz2 = Class.forName("com.wy.reflect.Student"); //class com.wy.reflect.StudentSystem.out.println(clazz2);

2 获取类的fields

通过反射机制获取某个类的某个属性,然后改变对应于这个类的某个实例的该属性值。
public FieldgetField(String name)
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口
的指定公共成员字段
public Field[] getFields()
返回一个包含某些 Field 对象的数组,这些对象反映此 Class
对象所表示的类或接口的所有可访问公共字段
public FieldgetDeclaredField(Stringname) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类
或接口的指定已声明字段
public Field[] getDeclaredFields()
返回 Field 对象的一个数组,这些对象反映此 Class 对象所
表示的类或接口所声明的所有字段

Field[] fields = clazz1.getFields();        System.out.println("---公共成员字段------");        for(Field f : fields) {            System.out.println(f);        }        System.out.println("---所有成员字段------");        fields = clazz1.getDeclaredFields();        for(Field f : fields) {            System.out.println(f+" ");        }

返回的结果:

---公共成员字段------public int com.wy.reflect.Student.scorepublic java.lang.String com.wy.reflect.Person.age---所有成员字段------private java.lang.String com.wy.reflect.Student.height public int com.wy.reflect.Student.score

总结:
getFileds返回的声明为public的属性,包括父类的属性。
getDeclaredFields返回了类中所有的属性,不包括父类的。

3 获取类的Method

通过反射机制得到某个类的某个方法,然后调用对应于这个类的某个实例的该方法。
public Method getMethod(String name,Class

Method[] methods = clazz1.getMethods();        System.out.println("---公共成员方法------");        for(Method m : methods) {            System.out.println(m);  //包含父类中public方法        }        methods = clazz1.getDeclaredMethods();        System.out.println("---所有成员方法------");        for(Method m : methods) {              System.out.println(m);  //不包含父类中方法        }

输出结果:
—公共成员方法——

public void com.wy.reflect.Student.getScore()public void com.wy.reflect.Person.getName()public final void java.lang.Object.wait() throws java.lang.InterruptedExceptionpublic final void java.lang.Object.wait(long,int) throws java.lang.InterruptedExceptionpublic final native void java.lang.Object.wait(long) throws java.lang.InterruptedExceptionpublic boolean java.lang.Object.equals(java.lang.Object)public java.lang.String java.lang.Object.toString()public native int java.lang.Object.hashCode()public final native java.lang.Class java.lang.Object.getClass()public final native void java.lang.Object.notify()public final native void java.lang.Object.notifyAll()---所有成员方法------private void com.wy.reflect.Student.setScore(int)public void com.wy.reflect.Student.getScore()private void com.wy.reflect.Student.getHeight()

4 获取类的构造器

通过反射机制获取某个类的构造器,然后调用该构造器创建该类的一个实例。
public Constructor getConstructor(Class

Constructor<?>[] constructors = clazz1.getConstructors();        System.out.println("---公共构造方法------");        for(Constructor<?> c : constructors) {            System.out.println(c);  //不包含父类中的构造方法        }        constructors = clazz1.getDeclaredConstructors();        System.out.println("---所有构造方法------");        for(Constructor<?> c : constructors) {            System.out.println(c);  //不包含父类中的构造方法        }

结果:

---公共构造方法------public com.wy.reflect.Student()---所有构造方法------public com.wy.reflect.Student()private com.wy.reflect.Student(java.lang.String)

5 创建类的实例对象

  • 调用Class对象的newInstance()方法

该方法会调用对象的默认构造器,如果没有默认构造器,会调用失败。

//有默认构造器,且为publicSystem.out.println(clazz1.newInstance());
  • 调用默认Constructor对象的newInstance方法

    Constructor<?> con = clazz1.getConstructor();System.out.println(con.newInstance());
  • 调用带参的构造方法

Constructor<?> con2 = clazz1.getConstructor(int.class);Student stu = (Student) con2.newInstance(12);System.out.println(stu + " " + stu.score);

注意:这里的构造器方法必须是public

6 调用类的函数

通过反射获取类的Method对象,调用Field的Invoke方法调用函数。

Method setScore = clazz1.getDeclaredMethod("setScore",int.class);        Student s = (Student) clazz1.newInstance();        //因为setScore是private方法,必须设置为true 表示在反射时取消java语言的反射检查        setScore.setAccessible(true);        setScore.invoke(s, 100);        System.out.println(s.score);

7 设置 获取类的属性值

通过反射获取类的Field对象,调用Field方法设置或获取值

//设置        Field f = clazz1.getDeclaredField("height");        f.setAccessible(true);        f.set(s, "100");        //获取        System.out.println(f.get(s));
0 0
原创粉丝点击