JAVA反射(Reflect)

一.反射定义

在运行期间,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的属性和方法,让对象认识到自身的结构。

二.反射实质

就是把JAVA类中的各种成分映射成一个个的JAVA对象
当我们new Student时,jvm会加载Student.class文件,jvm会去我们本地磁盘找Student.class文件,并加载到jvm内存中,一个类只产生一个class对象。
反射的本质就是得到class对象后,反向获取Student对象的各种信息

三.反射的使用

首先建一个User类

public class User {
    private int age;
    private String name;
    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;
    }
    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
    public User() {
    }

}

1.获取对象的类型
方式一.
Object.getClass() //获取方法属性首先应获取对象类型
方式二
Class.forName() //根据类型名字获取对象类型,注意类型名前要加上包名
方式三.
类名.class

public static void main(String[] args) throws ClassNotFoundException {
        //方式一
        System.out.println(new User().getClass());
        //方式二
        Class<?> aClass = Class.forName("reflectTest.User");//带包名的类路径,包名.类名
        System.out.println(aClass);
        //这个类型信息在jvm仍表现为一个对象,而且只有一份,判断第一种方式获取的Class对象和第二种方式获取的是否是同一个,结果为true,证明是同一对象
        System.out.println(new User().getClass()==Class.forName("reflectTest.User"));
        //方式三
        System.out.println(User.class);
    }

在运行期间,一个类,只有一个Class对象产生,常用第二种方法
2.类对象功能
(1).用反射方式创建对象
正常创建对象:new 类名();
反射创建对象:类对象.newInstance();
通过类对象创建一个实例,限制条件:要求对象有无参构造,且构造方法不能是私有的

User user = User.class.newInstance();
        System.out.println(user);

(2)获取方法信息
1.批量的:

  •  public Method[] getMethods():获取所有"公有方法"(public),返回Method[]数组,(包含了父类的方法也包含Object类)
    

类对象.getMethods();

  •  public Method[] getDeclaredMethods():获取本类所有的成员方法,包括(public,private,protected,不加)(不包括继承的)
    

2.获取单个的:

  •  public Method getMethod(String name,Class<?>... parameterTypes):
     参数:name : 方法名;Class ... : 形参参数类型
    
  •  public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
    
public class User {
    private int age;
    private String name;
    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;
    }
    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
    public User() {
    }
    //**************成员方法***************//
    public void show1(String s){
        System.out.println("调用了:公有的,String参数的show1(): s = " + s);
    }
    protected void show2(){
        System.out.println("调用了:受保护的,无参的show2()");
    }
    void show3(){
        System.out.println("调用了:默认的,无参的show3()");
    }
    private String show4(int age){
        System.out.println("调用了,私有的,并且有返回值的,int参数的show4(): age = " + age);
        return "abcd";
    }
    public void m1(int a, int b) {
        System.out.println("m1(int a, int b)被执行");
    }
    private void m1() {
        System.out.println("m1被执行");
    }
}
        System.out.println("调用所有公共方法");
        Class<?> aClass = Class.forName("reflectTest.User");
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("调用所有方法");
        Method[] methods1 = aClass.getDeclaredMethods();
        for (Method method : methods1) {
            System.out.println(methods1);
        }
        System.out.println("获取单个公共show1方法");
        Method show1 = aClass.getMethod("show1", String.class);
        System.out.println(show1);
        System.out.println("获取私有show4方法");
        Method show4 = aClass.getDeclaredMethod("show4", int.class);
        System.out.println(show4);
        System.out.println("获取多个形参公共方法");
        Method m1 = aClass.getMethod("m1", int.class, int.class);
        System.out.println(m1);
        System.out.println("无参方法");
        Method m11 = aClass.getDeclaredMethod("m1");
        System.out.println(m11);

(3).获取属性信息
a.类对象.getFields(); //获取 所有的公共属性,包括继承的,返回Field[]数组
b.类对象.getDeclaredFields() ; //获取本类所有属性(public,private,protected,不加)
c.类对象.getField(“属性名”) //获取某个公共属性
d.类对象.getDeclaredField(“属性名”) //获取某个属性(public,private,protected,不加)
e.设置字段的值:
Field --> public void set(Object obj,Object value):
参数说明:
1.obj:要设置的字段所在的对象;
应先获取对象
Object o = aClass.getConstructor().newInstance();//获取对象
2.value:要为字段设置的值;

public class Student {
    public Student(){

    }
    //**********字段*************//
    public String name;
    protected int age;
    char sex;
    private String phoneNum;

    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", sex=" + sex
                + ", phoneNum=" + phoneNum + "]";
    }
}
 public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<?> aClass = Class.forName("reflectTest.Student");
        System.out.println("获取所有公共属性");
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("获取所有属性");
        Field[] fields1 = aClass.getDeclaredFields();
        for (Field field1 : fields1) {
            System.out.println(field1);
        }
        System.out.println("获取公共属性name");
        Field name = aClass.getField("name");
        System.out.println(name);
        Object o = aClass.getConstructor().newInstance();//获取对象,需创建无参构造
        name.set(o,"张小雨");///为Student对象中的name属性赋值--》stu.name = "XXX“”
        Student stu=(Student)o;
        System.out.println(stu.name);
        System.out.println("获取私有属性");
        Field phoneNum = aClass.getDeclaredField("phoneNum");
        System.out.println(phoneNum);
        phoneNum.setAccessible(true);//暴力反射,解除私有限定
        phoneNum.set(o, "18888889999");
        System.out.println(stu);//私有属性需get/set方法
    }

(4).获取构造方法
1).批量的方法:
类对象.getConstructors():所有"公有的"构造方法,返回Constructor[]数组
类对象.getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有的
2).获取单个的方法,并调用:
类对象.getConstructor(Class… parameterTypes):获取单个的"公有的"构造方法:
类对象. getDeclaredConstructor(Class… parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;

//(默认的构造方法)
    Student(String str){
        System.out.println("(默认)的构造方法 s = " + str);
    }
    //无参构造方法
    public Student(){
        System.out.println("调用了公有、无参构造方法执行了。。。");
    }
    //有一个参数的构造方法
    public Student(char name){
        System.out.println("姓名:" + name);
    }
    //有多个参数的构造方法
    public Student(String name ,int age){
        System.out.println("姓名:"+name+"年龄:"+ age);//这的执行效率有问题,以后解决。
    }
    //受保护的构造方法
    protected Student(boolean n){
        System.out.println("受保护的构造方法 n = " + n);
    }
    //私有构造方法
    private Student(int age){
        System.out.println("私有的构造方法   年龄:"+ age);
    }
 System.out.println("获取所有构造方法");
        Constructor[] constructors = aClass.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("获取所有构造方法");
        Constructor[] constructors1 = aClass.getDeclaredConstructors();
        for (Constructor constructor11 : constructors1) {
            System.out.println(constructor11);
        }
        System.out.println("获取公有、无参的构造方法");
        Constructor constructor2= aClass.getConstructor();
        System.out.println(constructor2);
        //调用构造方法
        Object obj = constructor2.newInstance();
        System.out.println("obj = " + obj);
        Student stu1 = (Student)obj;
        System.out.println(stu1);
        System.out.println("获取私有构造方法");
        Constructor constructor3 = aClass.getDeclaredConstructor(int.class);
        System.out.println(constructor3);
        constructor3.setAccessible(true);
        constructor3.newInstance(28);
        System.out.println(stu1.age);

(5).反射调用方法
正常调用:对象.方法名(参数)
反射调用:方法.invoke(对象,参数)//方法在哪个对象上执行

       User u = new User();
        // 方法.invoke(对象, 参数);
        Method m = User.class.getDeclaredMethod("m1");
        m.setAccessible(true); // 设置这个方法可以被访问,可以突破访问修饰符的限制
        m.invoke(u); // 反射调用方法(性能低)

        // 反射调用 public void m1(int a)
        Method m12 = User.class.getDeclaredMethod("m1", int.class);
        m12.invoke(u, 1);

        Method m13 = User.class.getDeclaredMethod("m1", int.class, int.class);
        m13.invoke(u, 4, 5);

反射调用缺点:调用复杂,效率极低
优点:可以访问私有方法,突破正常方法的限制

私有方法
      private Student() {
        System.out.println("私有构造被调用");
     }
    // 调用私有构造
        Constructor<Student> cons = Student.class.getDeclaredConstructor();
        cons.setAccessible(true);
        Student s = cons.newInstance();
        System.out.println(s);

三.类加载器

加载一个不再classPath下的类

 ClassLoader cl = new ClassLoader() {
            @Override
            protected Class<?> findClass(String name) throws ClassNotFoundException {
                try {
                    FileInputStream in  = new FileInputStream("F:\\JAVAclass\\day201201_1\\Treasure.class");
                    byte[] bytes = new byte[1024*8];
                    int len = in.read(bytes);

                    // 调用父类的方法根据字节数组加载类
                    return defineClass(name, bytes, 0, len);
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
        };
        Class<?> clazz = cl.loadClass("com.westos.Treasure"); // 根据类名加载类, 得到类对象
        Constructor<?> constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);
        Object o = constructor.newInstance();//私有构造获取对象,可以进一步获取方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值