java基础:反射


反射


1. 什么是反射

反射是一种获取类信息的能力
什么是类信息:方法、变量(全局变量)、接口、父类构造器…

2.为什么会有发射

需要获取类信息

3. 发射是如何工作的

程序运行的三个阶段,想要反射获取类信息,必须先进入第二阶段:类对象阶段。
在这里插入图片描述
获取类对象的三种方案:
①在磁盘阶段:全类名就是——包名(地址)加类名(名称)
②类对象阶段:
③运行时阶段:
在这里插入图片描述

想要获取类信息,就必须进入类对象阶段
三种方案:
第一种:Class.forName(“全类名”)

package 反射;

public class Student {
    private String name="张三";
    public Integer age=18;
    Character sex='男';
    protected Double height =185.5;
}

package 反射;

public class Test {
    public static void main(String[] args) throws Exception{
        Class class1=Class.forName("反射.Student");
        Class class2=Student.class;
        Student student=new Student();
        Class class3=student.getClass();
        System.out.println(class1==class2);
        System.out.println(class2==class3);
        //最后会发现输出结果都是true,
        //==比较对象的地址是否相同,
        //这说明,这三个指向的地址一样

    }
}

地址都是方法区的这一块
同一个对象,会在方法区里面留下同一个类对象
在这里插入图片描述

4. 如何获取变量信息

package 反射;

public class Student {
    private String name="张三";
    public Integer age=18;
    Character sex='男';
    protected Double height =185.5;
}


package 反射;

import java.lang.reflect.Field;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) throws Exception{
        Class class1=Class.forName("反射.Student");
        //类的信息全部存储在类信息中
        //获取全部的全局变量信息,并进行打印---getDeclaredFields()
        Field[] files=class1.getDeclaredFields();
        System.out.println(Arrays.toString(files));
        System.out.println("-------------------------------");
        //获取public 修饰的全部变量信息,并进行打印---getFields()
        Field[] files1=class1.getFields();
        System.out.println(Arrays.toString(files1));
        System.out.println("-------------------------------");
        //获取指定的变量信息,并进行打印---getDeclaredField
        Field nameField =class1.getDeclaredField("name");
        System.out.println(nameField);
        Field heightField=class1.getDeclaredField("height");
        System.out.println(heightField);
        Field ageField = class1.getDeclaredField("age");
        System.out.println(ageField);
        System.out.println("-------------//------------------");
        //获取指定的,并且是public修饰的变量信息,并进行打印---getField
//        Field nameField1 =class1.getField("name");
//        System.out.println(nameField);
        //报错,不能输出private修饰符修饰的
//        Field heightField1=class1.getField("height");
//        System.out.println(heightField);
        //报错,不能输出protected修饰符修饰的
        Field ageField1 = class1.getField("age");
        System.out.println(ageField1);


    }
}

结果

D:\develop\Java\jdk1.8.0_261\bin\java.exe "-javaagent:D:\idea\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar=58405:D:\idea\IntelliJ IDEA 2021.2.1\bin" -Dfile.encoding=UTF-8 -classpath D:\develop\Java\jdk1.8.0_261\jre\lib\charsets.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\deploy.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\ext\access-bridge-64.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\ext\cldrdata.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\ext\dnsns.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\ext\jaccess.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\ext\jfxrt.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\ext\localedata.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\ext\nashorn.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\ext\sunec.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\ext\sunjce_provider.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\ext\sunmscapi.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\ext\sunpkcs11.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\ext\zipfs.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\javaws.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\jce.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\jfr.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\jfxswt.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\jsse.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\management-agent.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\plugin.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\resources.jar;D:\develop\Java\jdk1.8.0_261\jre\lib\rt.jar;D:\summerfirst\out\production\summerfirst 反射.Test
[private java.lang.String 反射.Student.name, public java.lang.Integer 反射.Student.age, java.lang.Character 反射.Student.sex, protected java.lang.Double 反射.Student.height]
-------------------------------
[public java.lang.Integer 反射.Student.age]
-------------------------------
private java.lang.String 反射.Student.name
protected java.lang.Double 反射.Student.height
public java.lang.Integer 反射.Student.age
-------------//------------------
public java.lang.Integer 反射.Student.age

进程已结束,退出代码为 0

5. 如何获取方法的信息

package 反射;

public class Student {
    private String name="张三";
    public Integer age=18;
    Character sex='男';
    protected Double height =185.5;
    public String color="蓝色";

    public void run(){}
    private int getAge(int age){
        return age;
    }
    void aaa(String name,Integer height){

    }
    protected void haha(String name,int age){}

}

package 反射;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) throws Exception{
        Class class1=Class.forName("反射.Student");
        //类的信息全部存储在类信息中
        //获取方法的信息
		
		//获取所有方法的信息
        Method[] declaredMethods=class1.getDeclaredMethods();
        System.out.println(Arrays.toString(declaredMethods));
        
        //获取public修饰的所有的方法的信息(还有来自父类object里面的)
        Method[] methods=class1.getMethods();
        System.out.println(Arrays.toString(methods));

        //获取指定的方法
        Method getAge = class1.getDeclaredMethod("getAge", int.class);//要把参数写上
        Method aaa = class1.getDeclaredMethod("aaa", String.class, Integer.class);
        Method run = class1.getDeclaredMethod("run");
        Method hhh = class1.getDeclaredMethod("haha" ,String.class,int.class);
        System.out.println(getAge);
        System.out.println(aaa);
        System.out.println(run);
        System.out.println(hhh);
		// getDeclaredMethod获取指定的,且是public的方法


//反射是获取类信息的能力

    }
}

结果
在这里插入图片描述

6. 如何获取构造器的信息

package 反射;

public class Student {
//变量
    private String name="张三";
    public Integer age=18;
    Character sex='男';
    protected Double height =185.5;
    public String color="蓝色";
//方法
    public void run(){}
    private int getAge(int age){
        return age;
    }
    void aaa(String name,Integer height){

    }
    protected void haha(String name,int age){}

//构造器
    public Student() {
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
//一般不设置私有类型的构造器
    public Student(String name, Integer age, Character sex, Double height, String color) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.height = height;
        this.color = color;
    }
}

package 反射;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) throws Exception{
        Class class1=Class.forName("反射.Student");
        //类的信息全部存储在类信息中
        //获取public修饰的,全部
        Constructor[] constructors=class1.getConstructors();
        System.out.println(Arrays.toString(constructors));
        //获取全部
        Constructor[] declaredConstructors = class1.getDeclaredConstructors();
        System.out.println(Arrays.toString(declaredConstructors));
        //获取指定的
        Constructor declaredConstructor = class1.getDeclaredConstructor(String.class,Integer.class);//传参数,不用写方法名
        System.out.println(declaredConstructor);
        Constructor declaredConstructor2 = class1.getDeclaredConstructor();
        Constructor declaredConstructor3 = class1.getDeclaredConstructor(String.class, Integer.class, Character.class, Double.class, String.class);
        System.out.println(declaredConstructor2);
        System.out.println(declaredConstructor3);
    }
}

结果
在这里插入图片描述

6. 获取构造器的类信息之后可以做什么

获取构造器之后:创建对象

package 反射;

public class Student {
    private String name="张三";
    public Integer age=18;
    Character sex='男';
    protected Double height =185.5;
    public String color="蓝色";

    public void run(){}
    private int getAge(int age){
        return age;
    }
    void aaa(String name,Integer height){

    }
    protected void haha(String name,int age){}


    private Student() {
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
//一般不设置私有类型的构造器
    public Student(String name, Integer age, Character sex, Double height, String color) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.height = height;
        this.color = color;
    }
}

package 反射;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) throws Exception{
        Class class1=Class.forName("反射.Student");
        //获取构造器的类信息
        Constructor declaredConstructor = class1.getDeclaredConstructor(String.class, Integer.class);
        //创建对象
        Student student1=(Student)declaredConstructor.newInstance("aaa",18);//传值,因为构造器需要传值
        //这里需要强转,因为默认是object类型

        //无参构造器
        Constructor declaredConstructor1 = class1.getDeclaredConstructor();
        //private修饰的数据,想要使用就必须暴力反射。
        declaredConstructor1.setAccessible(true);
        Student student2=(Student) declaredConstructor1.newInstance();
    }
}

7. 获取方法,调用方法

package 反射;

public class Student {
    private String name="张三";
    public Integer age=18;
    Character sex='男';
    protected Double height =185.5;
    public String color="蓝色";

    public void run(){
        System.out.println("这是run()");
    }
    private int getAge(int age){
        System.out.println("age()");
        return age;
    }
    void aaa(String name,Integer height){
        System.out.println("aaa()");
    }
    protected void haha(String name,int age){
        System.out.println("haha()");
    }


    private Student() {
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
//一般不设置私有类型的构造器
    public Student(String name, Integer age, Character sex, Double height, String color) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.height = height;
        this.color = color;
    }
}

package 反射;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) throws Exception{
        Class class1=Class.forName("反射.Student");
        //获取构造器的类信息
        Constructor declaredConstructor = class1.getDeclaredConstructor(String.class, Integer.class);
        //创建对象
        Student student1=(Student)declaredConstructor.newInstance("aaa",18);//传值,因为构造器需要传值
        //这里需要强转,因为默认是object类型


        Method run = class1.getDeclaredMethod("run");//获取方法
        Object invoke = run.invoke(student1);//使用方法——invoke()里面有两个东西,第一个是对象,第二个是参数(run方法没有参数)
        //为什么里面要传对象——》所有方法要是想要运行,必须先在内存里面开辟空间
        Method getAge = class1.getDeclaredMethod("getAge", int.class);
        getAge.setAccessible(true);//暴力反射(因为getAge是private修饰的)
        getAge.invoke(student1,18);//传对象,传参数
        Method aaa=class1.getDeclaredMethod("aaa",String.class,Integer.class);
        aaa.invoke(student1,"admin",199);
        Method haha=class1.getDeclaredMethod("haha",String.class,int.class);
        haha.invoke(student1,"admin",99);

    }
}

7. 获取变量

package 反射;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) throws Exception{
        Class class1=Class.forName("反射.Student");
        //获取构造器的类信息
        Constructor declaredConstructor = class1.getDeclaredConstructor(String.class, Integer.class);
        //创建对象
        Student student1=(Student)declaredConstructor.newInstance("aaa",18);//传值,因为构造器需要传值
        //这里需要强转,因为默认是object类型

        Field name=class1.getDeclaredField("name");
        name.setAccessible(true);//暴力反射
//        name.set(student1,"admin");
        System.out.println(name.get(student1));

        Field age=class1.getDeclaredField("age");
        age.set(student1,88);//赋值取值操作
        System.out.println(age.get(student1));

        Field sex=class1.getDeclaredField("sex");
        sex.set(student1,'女');
        System.out.println(sex.get(student1));

        Field height=class1.getDeclaredField("height");
        height.set(student1,189.89);
        System.out.println(height.get(student1));


    }
}

8.练习题

package 反射;
public class Student {
    private String name;
    private int age;
    private String address;

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

    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 String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}
package 反射;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

public class Test {
//①获取该类的构造方法来构造对象,
//②获取该类的名称和该类中的每一个变量的名称和方法的名称,并执行相关方法
//③给每一个变量赋值,并获取值
//④执行每一个构造方法meiyou
//⑤执行相应的方法
    public static void main(String[] args) throws Exception{
        //①获取该类的构造方法来构造对象,
        //,类的信息全部存储在类信息中 获取Student类的Class对象
        Class class1=Class.forName("反射.Student");
        //获取全部构造器,获取构造器的类信息
        Constructor declaredConstructor = class1.getDeclaredConstructor(String.class, int.class, String.class);
        //创建对象,  传值,因为构造器需要传值,  这里需要强转,因为默认是object类型
        Student student1=(Student)declaredConstructor.newInstance("张三", 20, "北京");

        // ②获取该类的名称和该类中的每一个变量的名称和方法的名称
        System.out.println("类名称: " + class1.getSimpleName());
        Field[] fields = class1.getDeclaredFields();
        for (Field field : fields) {
            System.out.println("字段名称: " + field.getName());
        }
        Method[] methods = class1.getMethods();
        for (Method method : methods) {
            System.out.println("方法名称: " + method.getName());
        }

        //③给每一个变量赋值,并获取值
        //代码通过getDeclaredField获取了name字段,并通过set方法给它赋了一个新值。
        Field name=class1.getDeclaredField("name");
        //暴力反射  如果字段是私有的,需要设置为可访问
        name.setAccessible(true);
        name.set(student1,"admin");
        System.out.println(name.get(student1));

        //代码通过getDeclaredField获取了age字段,并通过set方法给它赋了一个新值。
        Field age=class1.getDeclaredField("age");
        //暴力反射  如果字段是私有的,需要设置为可访问
        age.setAccessible(true);
        age.set(student1,18);
        System.out.println(age.get(student1));

        //代码通过getDeclaredField获取了name字段,并通过set方法给它赋了一个新值。
        Field address=class1.getDeclaredField("address");
        //暴力反射  如果字段是私有的,需要设置为可访问
        address.setAccessible(true);
        address.set(student1,"北京");
        System.out.println(address.get(student1));

        //⑤执行相应的方法
        //获取方法
        Method getName = class1.getDeclaredMethod("getName");
        //使用方法   ——》invoke()里面有两个东西,第一个是对象,第二个是参数(run方法没有参数)
        //为什么里面要传对象——》所有方法要是想要运行,必须先在内存里面开辟空间
        Object studentName = getName.invoke(student1);
        System.out.println("学生姓名: " + studentName);


    }
}

总结

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值