java中的反射详解

反射

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

简介

反射是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.Student
System.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.score
public 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.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public 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()方法

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

//有默认构造器,且为public
System.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));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值