Java中的反射

反射是什么?

反射是 Java 的高级特性,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。
反射就是可以在程序运行的时候动态装载类,查看类的信息,生成对象,或操作生成的对象。

反射机制的常用方法

获取类的相关信息的方法

1. Java 反射实现的关键点之 Class

Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM 已经帮我们创建好了。所有的对象都有getObject()方法,可以获取这个类的Class对象;

2. getName() 方法和.getPackage()方法

String getName();返回此 Member 表示的底层成员或构造方法的简单名称。
getPackage():返回类的存放路径

3. getSuperclass() 方法
public Class<? super T> getSuperclass()

返回:此对象继承的类。

4. getConstructors() 方法
public Constructor< ? >[] getConstructors() throws SecurityException

返回:公共构造方法的 Constructor 对象数组

5. getDeclaredConstructors() 方法
public Constructor<?>[] getDeclaredConstructors() throws SecurityException

返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
这里注意,在这些get方法中,加上Declared的都是获取所有类型,没有的,只能获取public类型
返回数组中的元素没有排序,也没有任何特定的顺序。如果该类存在一个默认构造方法,则它包含在返回的数组中。 如果此 Class 对象表示一个接口、一个基本类型、一个数组类或 void,则此方法返回一个长度为 0 的数组。
返回:表示此类所有已声明的构造方法的 Constructor 对象的数组

6. getFields() 方法
public Field[] getFields()  throws SecurityException`

返回:public属性的 成员变量数组

7.getField(Srtring name)
public Field getField(Srtring name)

返回:名为namen的public属性的 成员变量

8.getMethods() 方法
public Method[] getMethods() throws SecurityException

返回:表示此类中public方法的 Method 对象的数组

9.getMethod() 方法
Method Class.getMethod(String name, Class<?>... parameterTypes)

返回:对象所声明的public方法

该方法的第一个参数name是要获得方法的名字,第二个参数parameterTypes是按声明顺序标识该方法形参类型。

反射调用构造器创建对象:

Constroctor类:代表构造方法
其中的方法:

  • newInstance(Object…initargs)使用构造器创建对象,传入参数
  • getParameterTypes()按照声明顺序获得该构造方法的参数类型的Class数组
  • setAccettible()如果构造方法的属性是私有的,不能有反射创建,传入一个参数true则允许创建

如果使用空参数构造器,就可以不获取构造器,直接使用这个类的Class对象的newInstance()

class Stu{
    public int age;
    public String name;
    private int id;

    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;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Stu(){

    }
    private Stu(int age,String name){
        this.age=age;
        this.id=1;
        this.name=name;
    }
    public Stu(int age,String name,int id){
        this.age=age;
        this.id=id;
        this.name=name;
    }

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

    public void show(){
        System.out.println(">>>>>>>>>");
    }
}
Class Cs=Stu.class;
			//这里要try cath异常
 			Constructor ct=Cs.getConstructor();//获取空构造器
 			//也可以使用 Stu suu=(Stu)Cs.newInstance();
            Stu suu=(Stu)ct.newInstance();//使用构造器创建对象
            suu.name="hhh";
            System.out.println(suu);

反射获取成员属性与赋值

Field类,对应成员变量
其中方法:
获取对象的该属性值:get(String name)
设置对象的该属性值:set(String name,Object…value)

Stu suu=new stu();
           stu.name="hhh";
            Field field=Cs.getField("name");
            System.out.println(field.get(suu));//输出   hhh
            field.set(suu,"aaaa");
            System.out.println(field.get(suu));//输出   aaaa

注意,虽然可以由getDeclaredField()获得私有的属性,但是,不能直接访问私有的属性,需要设置忽略安全:
field.setAccessible(true)

反射调用方法

Method 类对应方法

执行方法
invoke( )方法,调用方法的对象,参数

Method md=Cs.getDeclaredMethod("show");//调用空show方法,参数为空
            md.invoke(suu);suu对象执行他的show()方法

getName()获取方法名称

反射的作用

可以降低类一类之间的依赖,降低耦合,更多的是设计框架。但是反射会影响运行效率。
有一些私有的属性无法从外面改变,就可以使用暴力反射来访问。