JavaSE 语法基础 --- 反射(基础知识问答+代码详解)

JavaSE 语法基础 — 反射(基础知识问答+代码详情)

反射是什么,简单介绍一下反射,说一说你对反射的理解?

反射是在运行状态中

对于任意一个类,都能够知道这个类的所有属性和方法;

对于任意一个对象,都能够调用它的任意一个方法和属性;

这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。

Java中的反射首先是能够获取到 Java 中要反射类的字节码获 取字节码有三种方法 :

Class.forName(className)

类名.class

this.getClass()

然后将字节码中的方法,变量,构造函数等映射成相应的 Method、Filed、Constructor 等类,这些类提供了丰富的方法可以被我们所使用。

Java反射API有几类?

反射 API 用来生成 JVM 中的类、接口或则对象的信息。

Class 类

反射的核心类,可以获取类的属性,方法等信息。

Field 类

Java.lang.reflec 包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值。

Method 类

Java.lang.reflec 包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法。

Constructor 类

Java.lang.reflec 包中的类,表示类的构造方法。

java反射创建对象效率高还是通过new创建对象的效率高?

通过new创建对象的效率比较高。

通过反射时,先找查找类资源,使用类加载器创建,过程比较繁琐,所以效率较低。

实例化对象的方式有哪些?

1.直接new一个对象

2.用反射获取到类对象,这个类对象用newInstance方法获取到一个实例

3.用反射获得构造器。Constructor类的newInstance() 获得实例对象

还有其他的方式,以后再补充…

哪里用到反射机制? 反射的应用场景有哪些?

1.JDBC中,利用反射动态加载了数据库驱动程序。

2.Web服务器中利用反射调用了Sevlet的服务方法。

3.Eclispe等开发工具利用反射动态刨析对象的类型与结构,动态提示对象的属性和方法。

4.很多框架都用到反射机制,注入属性,调用方法,如Spring。

获取到class对象的方式

Class.forName(“全类名”)

类名.class

对象.getClass()

class Teacher{
    private String name ="小明";
    private int id = 8;
    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                ", id=" + id +
                '}';
    }
}


public class TestDemo {


     public static void main(String[] args) throws ClassNotFoundException {

        // 获取到 Teacher 类对象的三种方式

        //1. 用类名.class 来获取具体的类对象, 用class 类型进行接收

        Class<?> c1 = Teacher.class;

        // 2. 用 Class.forName 获取具体的类对象

        Class<?> c2 = Class.forName("Teacher");

        // 3.用 Object类底下的 getClass 方法获取到类对象

        Teacher teacher = new Teacher();
        Class<?> c3 = teacher.getClass();

        System.out.println(c1==c3);
        System.out.println(c1==c2);
        System.out.println(c2==c3);
        
        // 结果都是true,说明获取到的类对象都是同一个。
    }

    
}


反射中的一些重要的类有哪些

Class类 、Field类、 Method类、 Constructor类

Class类

先获取到一个类,然后用Class类型接收,Class类中有各种获取 类内部属性方法的 方法,还可以用类创建一个实例。

获取到属性

返回值是 Field、Field[]

在这里插入图片描述

获取到方法

返回值是 Method、Method[]

在这里插入图片描述

获取到构造器

返回值是 Constructor、Constructors[]

在这里插入图片描述

其他的方法

在这里插入图片描述

Field类

getField()

没有参数,可以直接拿到这个类的私有属性

这个主要是用来接收 类获取的属性的,

setAccessiable(true) 设置权限

如果获取到的是类内部的私有属性,我们必须设置权限,有一个方法 Field类的 setAccessiable(true),把权限放开

set(实例对象,字段修改的具体内容) 修改对象的属性内容

然后修改具体属性,用一个Field类的set()方法,第一个参数是一个实例对象,第二个参数是修改的数据内容,意思就是修改这个实例对象中对应字段的属性内容为第二个参数。

举个例子看就行了不用背:

class Teacher{
    private String name ="小明";
    private int id = 8;

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

public class TestDemo{
    
    public static void main(String[] args){
           // 先获取到类对象
           Class<?> c =Teacher.class;
//           获取到实例对象
        Teacher teacher  =(Teacher)c.newInstance();

//      获取到类中的私有属性
        Field field = c.getDeclaredField("name");
//        设置权限
        field.setAccessible(true);
//        修改对象中的数据
        field.set(teacher,"小红");
        System.out.println(teacher);
    }
    
}
Method类

拿到具体类中的私有方法

getDeclaredMethod(方法名字,传参类型1,传参类型2…)

第一个参数,是我们要拿到那个方法,要传一个方法名

后面的参数,是我们拿到了这个方法后,要传参,所以后面的参数都是方法传入参数的类型。

和上面访问私有属性差不多,只不过内部使用的方法不一样,下面具体说一下

steAccessiable(true)

调用私有方法,要放开权限,设置参数为true

invoke(实例对象,具体参数1,具体参数2)

和这个对应的就是 Field里面的 set方法,set方法是修改私有属性,invoke是调用私有方法

第一个参数是实例对象,后面参数是传入参数的具体内容

class Teacher{
    private String name ="小明";
    private int id = 8;

    private int Nums(){
        return 1;
    }

    private int Nums2(int nums){
        return nums;
    }

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

public class TestDemo {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        // 先获取到类对象
           Class<?> c =Teacher.class;
//           获取到实例对象
        Teacher teacher  =(Teacher)c.newInstance();

//        拿到这个类中的私有方法-- 不带参数的nums1方法
        Method method = c.getDeclaredMethod("Nums");
        method.setAccessible(true);
        method.invoke(teacher);

//        拿到这个类的 带有参数的私有方法 nums2
        Method method1 = c.getDeclaredMethod("Nums2", int.class);
        // 这个拿到私有方法,主要传一个私有方法的名字(说明你要拿到那个方法),第二个拿到这个方法你要传入参数,后面的参数就是要传入的参数.class
        
        method1.setAccessible(true);
        method1.invoke(teacher, 3);
    }
        
}
Constructor类

拿到私有的构造器

getDeclaredConstructor(传参类型1.class,传参类型2.calss);

getDeclaredConstructor()获取到私有的构造方法

setAccessiable(true)

开放调用私有构造方法的权限

newInstance(具体参数,具体参数)

用构造方法直接newInstance创建一个实例,在参数里写 具体的构造参数

class Teacher{
    private String name ="小明";
    private int id = 8;

    private Teacher(String name, int id) {
        this.name = name;
        this.id = id;
    }

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

public class TestDemo {


    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        // 先获取到类对象
           Class<?> c =Teacher.class;

           // 拿到私有的构造方法,在参数里面写 构造方法参数的.class
          Constructor<?> constructor = c.getDeclaredConstructor(String.class,int.class);
          
          // 方法调用私有构造方法的权限
          constructor.setAccessible(true);
          
         // 使用 constructor.newInstance 获取到实例对象
          Object teacher =  constructor.newInstance("小红",2);

如何修改对象的私有属性?

先拿到类对象,这个类对象使用getDeclaredField() 方法拿到对应的属性,用Field进行接收。

调用 Field类的 setAccessiable(true) 开放访问的权限

调用 Field类的 set(实例对象,修改内容) ,修改具体对象的 私有属性内容

如何调用私有的类方法?

先拿到类对象,这个类对象使用getDeclaredMethod(方法名,参数.calss) 方法拿到类的私有方法,用Method进行接收。

调用 Method类的 setAccessiable(true) 开放访问的权限

调用 Method类的 invoke(实例对象,传入参数) ,调用实例对象的私有方法。

如何调用类的私有的构造方法?

先拿到类对象,这个类对象使用getDeclaredConstructor(构造参数.calss) 方法拿到类的私有构造器,用Constructor进行接收。

调用 Constructor类的 setAccessiable(true) 开放访问的权限

调用 Constructor类的 newInstance(传入具体参数) ,创建一个调用了对应构造器的实例对象。

Java 反射机制的好处和坏处

优点

1.对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法

2.增加程序的灵活性和扩展性,降低耦合性,提高自适应能力

缺点

反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;

反射调用方法时可以忽略权限检查,获取这个类的私有方法和属性,因此可能会破坏类的封装性而导致安全问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RAIN 7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值