概念既定

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。简单的来说反射是:指程序可以访问、检测和修改它本身状态或行为的一种能力

用途用法

在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法


 一切反射相关的代码都从获得类(java.lang.Class)对象开始,下面是获取类对象三种方法

1 Class.forName(完整类名)
2 类名.class
3 类实例对象.getClass()

在获取类对象是如果报ClassNotFoundException异常,则是类名错误,或者没有导包。

同一个类的、类对象只会创建一个

先创建一个Student类,如下:

public class Student {
    private String sid;

    private String sname;

    public Integer age;
    
    static{
        System.out.println("加载进jvm中!");
    }

    public Student() {
        super();
        System.out.println("调用无参构造方法创建了一个学生对象");
    }

    public Student(String sid) {
        super();
        this.sid = sid;
        System.out.println("调用带一个参数的构造方法创建了一个学生对象");
    }

    public Student(String sid, String sname) {
        super();
        this.sid = sid;
        this.sname = sname;
        System.out.println("调用带二个参数的构造方法创建了一个学生对象");
    }

    @SuppressWarnings("unused")
    private Student(Integer age) {
        System.out.println("调用Student类私有的构造方法创建一个学生对象");
        this.age = age;
    }

    public String getSid() {
        return sid;
    }

    public void setSid(String sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public void hello() {
        System.out.println("你好!我是" + this.sname);
    }

    public void hello(String name) {
        System.out.println(name + "你好!我是" + this.sname);
    }

    @SuppressWarnings("unused")
    private Integer add(Integer a, Integer b) {
        return new Integer(a.intValue() + b.intValue());
    }

    @Override
    public String toString() {
        return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
    }
}

获取类对象

public class Dome1 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1,类名.Class.forName
        Class<?> clz = Class.forName("com.zking.reflect.Student");
        // 2,类名.class
        Class<?> clz1 = Student.class;
        // 3,类实例对象.getClass()
        Student stu = new Student();
        Class<?> clz2 = stu.getClass();
        System.out.println(clz);
        System.out.println(clz1);
        System.out.println(clz2);

    }

 

反射三大作用

1 实例化对象(能够实例化未知的对象 能够通过私有构造器创建实例)

 

c实例.newInstance()

getConstructor只能寻找到public的修饰的构造器,getDeclaredConstructor可以寻找到任何修饰符修饰的构造器

如果报java.lang.NoSuchMethodException的错,表示构造器方法是private修饰的,要使用getDeclaredConstructor方法

如果使用getDeclaredConstructor报错:

java.lang.IllegalAccessException: Class com.zking.reflect.Demo2 can not access a member of class com.zking.reflect.Student with modifiers "private"

是因为,private方法无法访问,需设置;

.setAccessible(true);

注:一定要提供一个无参构造器

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Demo2 {
    public static void main(String[] args) throws Exception {

        Class clz = Student.class;
//        反射调用无参构造方法创建了一个学生对象
        Student stu = (Student) clz.newInstance();
//        要拿到构造类
        Constructor con=clz.getConstructor(String.class);
        
//        通过构造器实例化对象
        Student stu1=(Student)con.newInstance("s001");
        
//        调用带二个参数的构造方法创建了一个学生对象
        Constructor con2=clz.getConstructor(String.class,String.class);
//        通过构造器实例化对象
        Student stu2=(Student)con2.newInstance("s001","zs");
        
//        调用Student类共有的构造方法创建一个学生对象
        Constructor con3=clz.getConstructor(String.class);
        Student stu3=(Student)con3.newInstance("s001");
        
        
//        调用Student类私有的构造方法创建一个学生对象
        Constructor con4=clz.getDeclaredConstructor(Integer.class);
        con4.setAccessible(true);
        //通过构造器实例化对象
        Student stu4=(Student)con4.newInstance(12);
        
        
    }
}

 

2 动态调用方法

public class Demo3 {

    public static void main(String[] args) throws Exception {
        Student stu=new Student();
        stu.hello();
        Class clz=stu.getClass();
        Method m= clz.getDeclaredMethod("hello");
        m.invoke(stu);
        
        
        Method m1= clz.getDeclaredMethod("add",Integer.class,Integer.class);
        m1.setAccessible(true);
//        invoke:如果反射动态调用的方法是被void所修饰,那么返回的就是null
//        如果反射动态调用的方法不被void所修饰, 那么返回的就是被调用的方法的返回值
        Object invoke=m1.invoke(stu,20,5);
        System.out.println(invoke);
    }
}

3 读写属性

public class Demo4 {

    public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
        Student stu=new Student("s001","ls");
        stu.age=22;
        Class clz=stu.getClass();
        Field[] fields=clz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            System.out.println(field.getName()+" : "+field.get(stu));
        }
    }
}

 

 

 

 

posted on 2019-06-16 18:56  旧城微冷  阅读(257)  评论(0编辑  收藏  举报