Java学习笔记——反射

1、反射概述

Java反射机制:是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大地增强程序的灵活性。

2、获取Class类的对象

我们要想通过反射去使用一个类,首先我们要获取到该类的字节码文件对象,也就是类型为Class类型的对象,这里我们提供了三种方法获取Class类型的对象:
①使用类的class属性来获取该类对应的Class对象。距离:Student.Class将会返回Student类对应的Class对象。
②调用对象的getClass()方法,返回该对象所属类对应的Class对象,该方法是Object类中的方法,所有的Java对象都可以调用。
③使用Class类中的静态方法forName(String className),该方法需要传入字符串参数,该字符串参数的值是某个类的全路径,也就是完整包名的路径。

3、反射获取构造方法并使用

Class类中用于获取构造方法的方法:
//Constructor<?>[] getConstructors​()返回一个包含Constructor对象的数组,Constructor对象反映了由该Class对象表示的类的所有公共构造函数。
//Constructor<?>[] getDeclaredConstructors​()返回反映由该Class对象表示的类声明的所有构造函数的Constructor对象的数组。
//Constructor<T> getConstructor​(Class<?>...parameterTypes)返回一个Constructor对象,该对象反映由该Class对象表示的类的指定公共构造函数。
//Constructor<T> getDeclaredConstructor​(Class<?>...parameterTypes)返回一个Constructor对象,该对象反映由此Class对象表示的类或接口的指定构造函数。

Constructor类中用于创建对象的方法
//TnewInstance​(Object...initargs)使用由此Constructor对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例。
基本数据类型也可以通过.class得到对应的Class类型

//public void setAccessible​(boolean flag)将此反射对象的accessible标志设置为指示的布尔值。值为true表示反射对象应该在使用Java语言访问控制时抑制检查。值为false表示反射对象应该在使用Java语言访问控制时执行检查,并在类描述中指出变体。
//学生类
public class Student {
    //三个成员变量,一个私有,一个默认,一个公共
    private String name;
    int age;
    public String address;

    //四个构造方法,一私有,一默认,两公共
    public Student() {}

    private Student(String name) {
        this.name = name;
    }

    Student(int age) {
        this.age = age;
    }

    public Student(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    //成员方法:一个私有,四个公共
   private void function() {
       System.out.println("function");
   }

   public void method1() {
       System.out.println("method1");
   }

    public void method2(String s) {
        System.out.println("method2" + s);
    }

    public String method3(String s, int i) {
        return s + "," + i;
    }

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

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException,
            InstantiationException, IllegalAccessException, InvocationTargetException {
//        Student s = new Student();
        //获取Class对象
        Class<?> c = Class.forName("myReflectDemo.Student");

        //基本数据类型也可以通过.class得到对应的Class类型
        Constructor<?> con = c.getConstructor(String.class, int.class, String.class);
        Object o = con.newInstance("张三丰", 30, "西安");
        System.out.println(o);

        System.out.println("----------");

        //暴力反射
        //public void setAccessible​(boolean flag)将此反射对象的accessible标志设置为指示的布尔值。
        // 值为true表示反射对象应该在使用Java语言访问控制时抑制检查。
        // 值为false表示反射对象应该在使用Java语言访问控制时执行检查,并在类描述中指出变体。
        Constructor<?> decon = c.getDeclaredConstructor(String.class);
        decon.setAccessible(true);
        Object o1 = decon.newInstance("张三丰");
        System.out.println(o1);
    }

运行结果:
Student{name =张三丰, age = 30, adress = 西安}
----------
Student{name =张三丰, age = 0, adress = null}

4、反射获取成员变量并使用

Class类中用于获取成员变量的方法:
//Field[] getFields​()返回一个包含Field对象的数组,Field对象反映由该Class对象表示的类或接口的所有可访问的公共字段。
//Field getField​(String name)返回一个Field对象,该对象反映由该Class对象表示的类或接口的指定公共成员字段。
//Field[] getDeclaredFields​()返回一个Field对象的数组,反映了由该Class对象表示的类或接口声明的所有字段。
//Field getDeclaredField​(String name)返回一个Field对象,该对象反映由该Class对象表示的类或接口的指定声明字段。

//voidset​(Object obj,Object value)	给obj对象的成员变量赋值为value	将指定的对象参数中由此Field对象表示的字段设置为指定的新值。
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException,
            NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("myReflectDemo.Student");

        //Student s = new Student();
        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();
        System.out.println(obj);
        System.out.println("----------");

        Field name = c.getDeclaredField("name");
        //public void setAccessible​(boolean flag)将此反射对象的accessible标志设置为指示的布尔值。 值为true表示反射对象应该在使用Java语言访问控制时抑制检查。
        // 值为false表示反射对象应该在使用Java语言访问控制时执行检查,并在类描述中指出变体。
        name.setAccessible(true);
        name.set(obj, "张三丰");
        System.out.println(obj);
        System.out.println("----------");

        Field age = c.getDeclaredField("age");
        age.setAccessible(true);
        age.set(obj, 36);
        System.out.println(obj);
        System.out.println("----------");

        Field field = c.getField("address");
        field.set(obj, "西安");
        System.out.println(obj);
    }
运行结果:
	Student{name =null, age = 0, adress = null}
	----------
	Student{name =张三丰, age = 0, adress = null}
	----------
	Student{name =张三丰, age = 36, adress = null}
	----------
	Student{name =张三丰, age = 36, adress = 西安}

5、反射获取成员方法并使用

Class类中用于获取成员方法的方法
//Method[] getMethods​()返回一个包含方法对象的数组,方法对象反映由该Class对象表示的类或接口的所有公共方法,包括由类或接口声明的对象以及从超类和超级接口继承的类。
//Method[] getDeclaredMethods​()返回一个包含方法对象的数组,方法对象反映由Class对象表示的类或接口的所有声明方法,包括public,protected,default(package)访问和私有方法,但不包括继承方法。
//Method getMethod​(Stringname,Class<?>...parameterTypes)返回一个方法对象,该对象反映由该Class对象表示的类或接口的指定公共成员方法。
//Method getDeclaredMethod​(Stringname,Class<?>...parameterTypes)返回一个方法对象,它反映此表示的类或接口的指定声明的方法Class对象。

Method类中用于调用成员方法的方法
//Objectinvoke​(Objectobj,Object...args)在具有指定参数的指定对象上调用此方法对象表示的基础方法。
 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("myReflectDemo.Student");

        //Method[] getMethods​() 返回一个包含 方法对象的数组,方法对象反映由该 Class对象表示的类或接口的所有公共方法,
        // 包括由类或接口声明的对象以及从超类和超级接口继承的类。
        Method[] methods = c.getMethods();
        for (Method m : methods) {
            System.out.println(m);
        }

        System.out.println("-------------");
        //Method[] getDeclaredMethods​() 返回一个包含 方法对象的数组,方法对象反映由 Class对象表示的类或接口的所有声明方法,
        // 包括public,protected,default(package)访问和私有方法,但不包括继承方法。
        Method[] dm = c.getDeclaredMethods();
        for (Method m : dm) {
            System.out.println(m);
        }
        System.out.println("-------------");
        //Method getMethod​(String name, Class<?>... parameterTypes) 返回一个方法对象,
        // 该对象反映由该 Class对象表示的类或接口的指定公共成员方法。
        Method method1 = c.getMethod("method1");
//        System.out.println(method1);
        //获取无参构造方法创建对象
        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();
       
        //Object invoke​(Object obj, Object... args) 在具有指定参数的指定对象上调用此方法对象表示的基础方法。
        //Object:返回值类型
        //obj:调用方法的对象
        //args:方法需要的参数
        method1.invoke(obj);
    }
运行结果:
	public java.lang.String myReflectDemo.Student.toString()
	public void myReflectDemo.Student.method1()
	public java.lang.String myReflectDemo.Student.method3(java.lang.String,int)
	public void myReflectDemo.Student.method2(java.lang.String)
	public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
	public final void java.lang.Object.wait() 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 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()
	-------------
	public java.lang.String myReflectDemo.Student.toString()
	private void myReflectDemo.Student.function()
	public void myReflectDemo.Student.method1()
	public java.lang.String myReflectDemo.Student.method3(java.lang.String,int)
	public void myReflectDemo.Student.method2(java.lang.String)
	-------------
	method1

获取成员方法案例

// 有一个ArrayList<Integer>集合,如何在这个集合中添加字符串元素?
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //创建集合对象
        ArrayList<Integer> array = new ArrayList<Integer>();


        //获取Class对象
        Class<? extends ArrayList> c = array.getClass();
        //获取add方法
        Method add = c.getMethod("add", Object.class);
        add.invoke(array, "hello");
        add.invoke(array, "world");
        add.invoke(array, "java");
        System.out.println(array);

    }
运行结果:
[hello, world, java]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值