JAVA反射机制

JAVA反射机制

1.反射:

反射就是把JAVA类中的各个成分映射成一个个的java对象。例如,一个类有:成员变量、普通方法、构造方法、包等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。

2.反射机制

主要是指程序可以访问、检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。
反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接,但是反射使用不当也会造成一定的影响。

3.反射机制的作用:

在运行时判断任意一个对象所属的类,在运行时获取类的对象,在运行时访问java对象的属性,方法,构造方法等。

4.反射机制的优点和缺点

在讨论优点和缺点之前可以了解下动态和静态的概念
静态编译:在编译时确定类型,绑定对象。即通过
动态编译:运行时确定类型,绑定对象,动态编译最大限度发挥了java的灵活性,体现了多态的应用,用以降低类之间的耦合性
所以反射机制优点为:可以动态创建对象和编译,体现出很大的灵活性,通过反射机制可以获得类的各种内容,进行了反编译,对于java这种先编译后运行的语言来说,反射机制使得代码更加灵活,更加容易实现面向对象。
比如:对于一个大型的软件,在编译完成上线之后,在发现需要更新功能时,不可能把用户以前用的卸载让用户安装新的版本,采用反射机制软件就可以不用卸载,只需要在运行的时动态的编译和创建,就可以实现该功能。
[以上摘自] (https://www.cnblogs.com/Eason-S/p/5851078.html)
接下来就对java的反射机制做以个人理解的介绍

  • 反射常用的java类型
  • 使用反射的基本步骤
  • Class类是java反射机制的起源和入口
  • Java反射常用类的具体介绍

一、Java反射常用类

Class类:可获取类和类的成员信息;
Field类:可访问类的属性:
Method类:可调用类的方法;
Constructor类:可调用类的构造方法:

二、使用反射的基本步骤:

1.导入包java.lang.reflect.*;
2.调用需要操作类的java.lang.Class对象;
3.调用Class的方法获取Field、Method等对象
4.使用反射API进行操作(设置属性、调用方法)

三、Class类是Java反射机制的起源和入口:

Clas类的实例化对象代表一个正在运行的Java类或接口。

  • 每个类都有自己的Class对象
  • 用于获取与类相关的各种信息
  • 提供了获取类信息的相关方法
  • Class类继承自Object类

Class类存放类的结构信息:

  • 类名
  • 父类、接口
  • 方法、构造方法、属性
  • 注释
四、Class类

1.获取Class对象的方式:
法1:Student stu = new Student();
Class clazz = stu.getClass;

法2:Class clazz = Student.class;
Class clazz = String.class

法3:Class clazz = Class.forName("java.lang.String");//包名.类名
Class clazz = Class.forName(java.util.Date);

具体的代码操作如下:
(接下来的代码都是对Student类加以的解析):

package reflect;

public class Student {

    private String name;
    private int age;
    private double score;

    public Student() {

    }

    public Student(String name,int age,double score){
        this.name = name;
        this.age = age;
        this.score = score;
    }

    public void learn(){
        System.out.println(name+"真能学习啊。。。");
    }

    public static void eat(){
        System.out.println("我喜欢吃葡萄。。。");
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }



}

通过上述三种方式获得Class对象,这里插一句:所有类的对象都是Class的实例

package reflect;

import java.lang.reflect.Modifier;

public class ClassDemo {

    public static void main(String[] args) {

        try {
            Student stu = new Student();
            //方式1获取Student类的类对象
            Class<? extends Student> clazz1= stu.getClass();
            //方式2获取
            Class<Student> clazz2 = Student.class;
            //方式3获取
            Class<?> clazz3 = Class.forName("reflect.Student");

            System.out.println("方式1获取的类对象名称为:"+clazz1.getName());
            System.out.println("方式2获取的类对象名称为:"+clazz2.getName());
            System.out.println("方式3获取的类对象名称为:"+clazz3.getName());

            int mod = clazz1.getModifiers(); //获取类的访问权限对应的整数值
            String str=Modifier.toString(mod);
            System.out.println("该类对应的访问权限名为:"+str);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

getName():获得Class对象的包名.类名
getSimpleName():获得Class对象的类名
getModifiers():获得属性修饰符对应的整数
Modifiers.toString(int mod):由修饰符对应的整数对应出来的对应的访问修饰符

Field类

Fileld[] getDeclaredFields(): 获取类的全部属性数组
getName(): 由属性对象的调用该方法是获得属性名
getType(): 获取属性的类型
int getModifiers(): 获取属性权限对应的整数值

接下来看下获取上面那个Student的几个属性值,可以完整的获得三个属性:

package fieldrefelect;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class FieldDemo {

    public static void main(String[] args) {

        //获取Student的Class实例
        Class<Student> clazz = Student.class;
        //获取Stuednt的Class实例的属性对象数组
        Field[] fields = clazz.getDeclaredFields();

        //遍历属性对象数组
        for(Field f : fields){
            String modifier = Modifier.toString(f.getModifiers()); //获取属性的权限值
            String returnType = f.getType().getSimpleName(); //获取属性类型
            String name = f.getName();
            System.out.println(modifier+" "+returnType+" "+name+";");
        }


    }

}

运行结果如图:

这里写图片描述

Method类

Method[] getDeclaredMethods(): 获取Class实例的全部方法对象构成的数组(一个方法就是一个方法对象)

拿代码更容易理解一哈:

package methodreflect;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class MethodReflect {

    public static void main(String[] args) {

        try {

            Class<?> clazz = Class.forName("methodreflect.Student");
            Method[] methods =  clazz.getDeclaredMethods();

            //遍历反射得到的方法数组
            for(Method method:methods){
                String methodName = method.getName(); //获得方法的名称
                String returnType = method.getReturnType().getSimpleName(); //获得方法的返回值类型
                String modifier = Modifier.toString(method.getModifiers()); //获得方法的权限名
                Class<?>[] paramTypes=method.getParameterTypes(); //获取参数类型的数组
                if(paramTypes.length == 0){
                    //当方法无参数时
                    System.out.println(modifier+" "+returnType+" "+methodName+"()");
                }else{
                    //当方法有参数时
                    for(int i=0;i<paramTypes.length;i++){
                        if(i!=paramTypes.length-1){
                            System.out.println(modifier+" "+returnType+" "+methodName+"("
                                    +paramTypes[i].getSimpleName()+" args"+i+",");
                        }else{
                            System.out.println(modifier+" "+returnType+" "+methodName+"("
                                    +paramTypes[i].getSimpleName()+" args"+i+")");
                        }
                    }
                }
                System.out.println();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }


}

运行结果如图所示:
这里写图片描述

学过得到方法对象以后就可以利用Class实例实例化对象反向调用方法了:

clazz.newInstance(): 获得Class对象对应类的无参构造对象

看代码把:

package methodreflect;

import java.lang.reflect.Method;

public class InvokeMethod {

    public static void main(String[] args) {

        try {

            Class<Student> clazz = Student.class; 
            Student stu = clazz.newInstance(); //利用Class实例创建对应类的无参构造对象
            Method setNameMethod = clazz.getDeclaredMethod("setName",String.class); //获得指定方法对象,
            //通过反射创建类的实例并调用方法
            setNameMethod.invoke(stu,"呱呱蛙"); //反向调用
            Method getNameMethod = clazz.getDeclaredMethod("getName");
            System.out.println(getNameMethod.invoke(stu));
            Method staticMethod = clazz.getDeclaredMethod("eat");
            staticMethod.invoke(stu);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

运行结果就是调用了方法了;

Constructor方法

直接上代码:

package constructor;

import java.lang.reflect.Constructor;

public class ConstructorDemo {

    public static void main(String[] args) {
        Class<Student> cls=Student.class;
        try {
          Constructor<Student>  cons=cls.getDeclaredConstructor(String.class,int.class,double.class); // 获取三参的构造方法
          Student stu=cons.newInstance("东方不败",20,99.5);   // 调用三参构造,实例化对象
          System.out.println(stu);
        } catch (Exception e) {
            e.printStackTrace();
        } 

    }

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值