有关反射

一、概念

  反射是Java的特征之一,是一种间接操作目标对象的机制,核心是JVM在运行的时候才动态加载类,并且对于任意一个类,都能够知道这个类的所有属性和方法,调用方法/访问属性,不需要提前在编译期知道运行的对象是谁,他允许运行中的Java程序获取类的信息,并且可以操作类或对象内部属性。
  程序中对象的类型一般都是在编译期就确定下来的,而当我们的程序在运行时,可能需要动态的加载一些类,这些类因为之前用不到,所以没有加载到jvm,这时,使用Java反射机制可以在运行期动态的创建对象并调用其属性,它是在运行时根据需要才加载。

二、反射的作用

即,创建对象。
由上述概念可知传统创建对象的问题是:

  • 传统方式创建对象: new 类名();(此时类名已知,但我们往往无法提前预知要执行的对象)
  • 若要修改使用的类,必须要修改源码

解决方法:

  • 当然是使用反射,动态创建对象啦(可以通过敲以下代码来感受反射的魅力)

三、反射的优缺点

优点:与传统的new静态创建对象相比,反射可以动态的创建对象。
缺点:反射的代码效率低,影响程序性能。

四、反射获取对象的三种方式

(一)根据全限定路径获取(常用)
//反射创建类对象,通过cla创建Person对象(其中forName中的参数是"包名.类名")
Class cla=Class.forName("com.jdbc.pojo.Person");
//newInstance()就是返回对象,其返回对象的类型为Object
Object obj=cla.newInstance();
//总结反射相比于传统创建对象的好处:当改变forName中的参数时,Object对象就随即改变(动态创建java对象)
(二)根据对象获取
//调用底层使用反射封装的方法
Class cla=Person.class;
(三)根据类名获取
//调用底层使用反射封装的方法
Class cla=new Person().getClass();
(四)注意

一个类只有一个类对象

五、操作属性、方法及构造器

在码操作属性部分的代码前先给出类Student及其父类Person:

package com.jdbc.pojo;

public class Student extends Person {
    //声明实体类属性
    public String sname;
    protected int sage;
    String sfav;
    private String ssex="男";
    public static int money=1000;

    public Student() {
        super();
    }

    public String sHi() {
        return "Hi reflect";
    }
    public String sHi(int num,String str) {
        System.out.println(str+num);
        return str+num;
    }
    public static String sHi(String str) {
        System.out.println(str);
        return str;
    }
    protected void sHello() {
        System.out.println("Student.sHello(protected)");
    }
    private void sHello1() {
        System.out.println("Student.sHello1(private)");
    }
    void sHello2() {
        System.out.println("Student.sHello2(default)");
    }
}
package com.jdbc.pojo;

public class Person {
    public String pname="张三";
    protected int page;
    String pfav;
    private String psex;

    public String pHi() {
        return "Hi reflect";
    }
    public String pHi(int num,String str) {
        return str+num;
    }
    protected void pHello() {
        System.out.println("Person.pHello(protected)");
    }
    private void pHello1() {
        System.out.println("Person.pHello1(private)");
    }
    void pHello2() {
        System.out.println("Person.pHello2(default)");
    }
}

接下来的部分是操作属性的代码:

package com.jdbc.reflect;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestReflect {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        //反射操作类属性
        operField();
        //反射操作类方法
        operMethod();
        //反射调用构造器
        operConstructor();
    }
    
    //反射操作类属性
    public static void operField() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
        //1.获取类对象
        Class cla=Class.forName("com.jdbc.pojo.Student");
        
        //2.获取反射类属性
        Field[] fds=cla.getFields();//获取该类以及父类的公共字段(public)
        for (Field f:fds) {
            System.out.println("获取属性名:"+f.getName());
        }
        Field[] fds2=cla.getDeclaredFields();//获取该类声明的所有字段
        Field fds3=cla.getField("sname");//指定获取该类及父类的public字段
        Field fds4=cla.getDeclaredField("sage");//指定获取该类的所有字段
        Field fds5=cla.getSuperclass().getDeclaredField("pname");//指定获取父类的所有字段,其中getSuperclass()是获取父类
        
        //3.操作类属性
            //获取静态属性值
                Field fs=cla.getDeclaredField("money");
                fs.set(null,2000);
                System.out.println(fs.get(null));//get()中的值为属性值,如果是静态变量放入null就好
            //获取非静态属性值
                Field fd=cla.getDeclaredField("sname");
                Object obj=cla.newInstance();
                fd.set(obj,"李四");
                System.out.println(fd.get(obj));//newInstance()返回该对象的实例化对象,相当于new Student();
                
        /*
        * 注意此处,不能直接写成:
        * fd.set(cla.newInstance(),"李四");
        * System.out.println(fs.get(cla.newInstance()));
        * 因为,这两行中的newInstance()是两个不同的对象
        * 
        * */
        /*
        * 与传统new Student()相比的不同是:
        * new Student()是先声明对象再获取
        * cla.newInstance()是先获取,再说是哪个对象的东西
        * 
        * */
        
            //获取private属性
                Field fd2=cla.getDeclaredField("ssex");
                fd2.setAccessible(true);//操作private属性,不安全
                Object obj2=cla.newInstance();//获取实例化对象
                System.out.println(fd2.get(obj2));
    }
    
    //反射操作类方法
    public static void operMethod() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        //1.获取类对象
        Class cla=Class.forName("com.jdbc.pojo.Student");
        
        //2.获取类方法对象
        Method[] ms=cla.getMethods();//获取该类以及父类的公共方法(public)
        Method[] ms2=cla.getDeclaredMethods();//获取该类声明的所有方法
        Method m=cla.getMethod("sHi",int.class,String.class);//指定获取该类及父类的public方法,由于方法重载,可在getMethod()中指明参数类型
        Method m2=cla.getDeclaredMethod("sHello",null);//指定获取该类的所有方法,由于该方法只有一个,所以可在getMethod()中添加null
        
        //3.执行方法
            //静态方法
                Method m3=cla.getDeclaredMethod("sHi",String.class);
                m3.invoke(null,"今天学习了反射,超开心");//对sHi传参
            //非静态方法
                Method m4=cla.getDeclaredMethod("sHi",int.class,String.class);
                m4.invoke(cla.newInstance(),100,"反射功能好强大");
    }
    
	//反射操作类构造器
	public static void operConstructor() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //1.获取类对象
        Class cla=Class.forName("com.jdbc.pojo.Student");
        
        //2.获取构造方法
        Constructor[] cs=cla.getConstructors();//获取该类的公共构造方法(public)
        Constructor[] cs1=cla.getDeclaredConstructors();//获取该类的所有构造方法
        Constructor c=cla.getConstructor(null);//获取该类指定的无参构造方法,也可在getConstructor()中填写null
        Constructor c2=cla.getConstructor(String.class);//获取该类指定的有参构造方法
        
        //3.执行构造方法
        Constructor c3=cla.getDeclaredConstructor(String.class);
        Object obj=c3.newInstance("moon");//传参
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值