java反射

什么是java反射

1.反射是框架的灵魂
2.在代码运行时在我们的磁盘中源码会被javac转换为字节码然后通过ClassLoader类加载器会在JVM内存中反射为相应的类对象。

获取反射类对象

获取类对象的方式有三种(我这里使用的是Student类)

Student类

package demo;

public class Student {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

反射类

package demo;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        //第一种:根据Student类路径获取Student的反射类对象
        Class<?> aClass = Class.forName("demo.Student");
        //第二种:根据类名获取Student类的反射对象
        Class<Student> fan1Class = Student.class;
        //第三种:通过类对象获取类的反射类对象
        Student f = new Student();
        Class<? extends Student> aClass1 = f.getClass();
        System.out.println(aClass1);
    }
}

通过反射类获取类对象

这里的类还是使用的上方的Student类
反射类

package demo;

public class Test1 {
    public static void main(String[] args) throws Exception {
        //根据Student类的路径获取反射类对象
        Class<Student> aClass = (Class<Student>) Class.forName("demo.Student");
        /**
         * 通过反射类得到相应的类对象---通过Student类对象调用newInstance
         * 通常都是用别人封装好的方法:new Student来获取Student对象
         *
         */
        Student student = aClass.newInstance();
    }
}

获取反射中的属性成员对象

源码转换为字节码后会以File类对象的形式存在。

Student类

package demo;

public class Student extends People {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Student父类People类

package demo;

public class People {
    public String address;
    private String watches;
}

测试类
通过属性名获取的时候如果属性为private时会报错误
Exception in thread “main” java.lang.NoSuchFieldException: watches
at java.lang.Class.getField(Class.java:1703)
at demo.Test2.main(Test2.java:27)
解决方法请看下文

package demo;

import java.lang.reflect.Field;

public class Test2 {
    public static void main(String[] args) throws Exception {
        //获取Student类的反射类
        Class<Student> studentClass = Student.class;
        /**
         * 获取反射类中的成员对象
         * getDeclaredFields获取本类中所有的属性对象
         */
        Field[] declaredFields = studentClass.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field);
        }
        /**
         * getFields获取本类以及父类中的public属性对象
         */
        Field[] fields = studentClass.getFields();
        for (Field f : fields) {
            System.out.println(f);
        }
        /**
         * getField通过属性的名字获取
         */
        Field address = studentClass.getField("address");
        System.out.println(address);
    }
}

Field类中的常用方法

Doctor类

package demo;

public class Doctor {
    @MyAnn(value = "年龄")
    private Integer age;
    public String name;

    @Override
    public String toString() {
        return "Doctor{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

注解MyAnn类

package demo;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * @Retention不写的话会报错误 Exception in thread "main" java.lang.NullPointerException
 * at demo.Test3.main(Test3.java:32)
 * 因为没有@Retention无法在反射时显现
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnn {
    String value();
}


测试类

package demo;

import java.lang.reflect.Field;

public class Test3 {
    public static void main(String[] args) throws Exception {
        //通过路径获取反射类对象
        Class<?> aClass = Class.forName("demo.Doctor");
        //通过反射类得到类对象
        Object o = aClass.newInstance();
        /**
         * 这时打印的为值为空
         * Doctor{age=null, name='null'}
         */
        System.out.println(o);
        //获取反射类中的name属性对象
        Field nameField = aClass.getDeclaredField("name");
        //通过name属性对象为Doctor对象赋值
        nameField.set(o, "小张");
        //打印结果为 Doctor{age=null, name='小张'}
        System.out.println(o);
        Field ageField = aClass.getDeclaredField("age");
        //age属性为私有的无法访问 需要设置允许否则回报上面遇到的错误
        ageField.setAccessible(true);
        ageField.set(o, 23);
        //打印Doctor{age=23, name='小张'}
        System.out.println(o);
        /*获取属性上的注解对象
         *打印--年龄
         */
        MyAnn annotation = ageField.getAnnotation(MyAnn.class);
        System.out.println(annotation.value());
    }
}

获取方法类对象

Method

teacher类

package demo2;

public class Teacher extends People{
    public String fun1() {
        System.out.println("--1");
        return "teacherMan";
    }

    public String fun1(int age) {
        System.out.println("==1");
        return "teacherMan";
    }

    public String fun2(int age) {
        System.out.println("==2");
        return "teacher" + age;
    }

    private void fun3() {
        System.out.println("++3");
    }
}

teacher父类people

package demo2;

public class People {
    public String fun() {
        System.out.println("p--");
        return "teacher";
    }

    private void fun2() {
        System.out.println("p==");
    }
}

测试类

package demo2;

import java.lang.reflect.Method;

public class Test3 {
    public static void main(String[] args) throws Exception {
        Class<Teacher> teacherClass = Teacher.class;
        teacherClass.newInstance();
        /**
         * 获取类中所有的Method方法对象
         * 输出
         * public java.lang.String demo2.Teacher.fun1(int)
         * public java.lang.String demo2.Teacher.fun1()
         * private void demo2.Teacher.fun3()
         * public java.lang.String demo2.Teacher.fun2(int)
         */
//        Method[] declaredMethods = teacherClass.getDeclaredMethods();
//        for (Method m:declaredMethods) {
//            System.out.println(m);
//        }
        /**
         * 获取本类以及父辈的中public修饰的方法对象--可以从输出值来判断
         * 输出
         * public java.lang.String demo2.Teacher.fun2(int)
         * public java.lang.String demo2.Teacher.fun1(int)
         * public java.lang.String demo2.Teacher.fun1()
         * public java.lang.String demo2.People.fun()
         * 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()
         */
//        Method[] methods = teacherClass.getMethods();
//        for (Method m:methods) {
//            System.out.println(m);
//        }
        /**
         * getMethod通过名字获取
         * 书写int.class参数输出结果为
         * public java.lang.String demo2.Teacher.fun1(int)
         * 没有书写参数时输出为
         * public java.lang.String demo2.Teacher.fun1()
         */
        Method fun1 = teacherClass.getMethod("fun1", int.class);
        System.out.println(fun1);
    }
}

Method类中常用方法

teacher类

package demo2;

public class Teacher extends People {
    public String fun1() {
        System.out.println("--1");
        return "teacherMan";
    }

    @My("你好")
    public String fun1(int age) {
        System.out.println("==1" + age);
        return "teacherMan";
    }

    public String fun2(int age) {
        System.out.println("==2");
        return age + "teacher";
    }

    private void fun3() {
        System.out.println("++3");
    }
}

注解

package demo2;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface My {
    String value();
}

测试

package demo2;

import java.lang.reflect.Method;

public class Test4 {
    public static void main(String[] args) throws Exception {
        Class<Teacher> teacherClass = Teacher.class;
        Teacher teacher = teacherClass.newInstance();
        Method fun = teacherClass.getMethod("fun1", int.class);
        //回调fun1方法  执行fun1方法
        Object invoke = fun.invoke(teacher, 23);
        System.out.println(invoke);
        //注解
        My annotation = fun.getAnnotation(My.class);
        System.out.println(annotation.value());
    }
}

获取构造对象

子类

package demo2;

public class Z extends F {
    public Z() {
        super();//默认拥有
        System.out.println("子类的无参");
    }

    public Z(String name) {
        System.out.println("子类的有参:" + name);
    }

    private Z(Integer age) {
        System.out.println("有参私有构造");
    }
}


父类

package demo2;

public class F {
    public F() {
        System.out.println("父类的无参");
    }

    public F(String name) {
        System.out.println("父类的有参:" + name);
    }

}

测试

package demo2;

import java.lang.reflect.Constructor;

public class Test5 {
    public static void main(String[] args) throws Exception {
        Class<Z> zClass = Z.class;
        Object o = zClass.newInstance(); //得到类对象---调用构造函数

        Constructor<?>[] declaredConstructors = zClass.getDeclaredConstructors();
        for (Constructor c : declaredConstructors) {
            System.out.println(c);
        }

        //它只能得到本类中public的构造函数
        Constructor<?>[] declaredConstructors2 = zClass.getConstructors();
        for (Constructor c : declaredConstructors2) {
            System.out.println(c);
        }
    }
}

constructor常用方法

其他类引用上面的
测试类

package demo2;

import java.lang.reflect.Constructor;

public class Test5 {
    public static void main(String[] args) throws Exception {
        Class<Z> zClass = Z.class;
        Object o = zClass.newInstance();
        Constructor<Z> declaredConstructor = zClass.getDeclaredConstructor(String.class);
        Z hello = declaredConstructor.newInstance("hello");
        System.out.println(hello);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值