反射学习(入门)

反射

1、作用

  • 在运行时分析类的能力
  • 在运行是检查对象,例如,编写一个适用于所有类的toString方法
  • 实现泛型数组操作代码
  • 利用Method对象(像C++中的指针)

2、Class类

在程序运行期间,Java运行时系统初始为所有对象维护一个运行时类型标识。这个信息会跟踪每一个对象所属的类。JVM利用运行时类型信息选择要执行的正确方法。

2.1、获取Class对象

getClass

Object中的getClass()会返回一个Class类型的实例

import Employee.Employee;

public class javaStydy05 {

    public static void main(String[] args) {
        Employee employee = new Employee("wang");
        Class cl = employee.getClass();
        System.out.println(cl);
        System.out.println(cl.getName());
    }
}

运行结果:
class Employee.Employee
Employee.Employee

如果类在一个包中,name包名也会作为类名的一部分

2.2、静态方法forName()

使用静态方法forName获取类名对应的Class对象

import Employee.Employee;

public class javaStydy05 {

    public static void main(String[] args) {

        Employee employee = new Employee("wang");
        Class cl2 = null;
        //forName()
        try {
             cl2 = Class.forName("Employee.Employee");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println(cl2);
    }
}

forName中传入的必须是类的全限定名

2.3、T.class

假设T是一个Java类型 那么T.class就可以得到其匹配的类对象

import Employee.Employee;

public class javaStydy05 {

    public static void main(String[] args) {
        Employee employee = new Employee("wang");
            
        //T.class
        Class cl3 = Employee.class;

      
        System.out.println(cl3);
    }
}

2.4、补充

可以直接用==比较两个类对象

当获取一个类对象时,可以使用getConstructor()的到一个Constructor类型的对象,然后通过它使用newInstance()构造一个实例

import Employee.Employee;

import java.lang.reflect.Constructor;

public class javaStudy06 {
    public static void main(String[] args) {
        Employee employee = new Employee("wyz");
        Class cl = null;
            try {
                cl = Class.forName("Employee.Employee");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        Constructor econstructor = null;
        Employee employee2 = null;
        try {
            econstructor = cl.getConstructor();
            employee2 = (Employee) econstructor.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println(employee2);

    }

}

通过这个方法只能使用无参构造器,如果目标类中没有无参构造器,则会抛出异常

利用反射分析类的能力

利用反射可以检查类的结构

  • java.lang.feflect包中有三个类Field(描述类的字段),Method(描述类的方法),Constructor(描述类的构造器)
  • 三个类中都有getName()用于返回字段,方法,构造器的名字
  • Field中有getType()用于返回字段类型的类对象

3、反射中常用方法

定义pojo类

package Reflect;


/**
 * person
 */
abstract class Person{
    public void sayHello(){}
}

/**
 * chinese
 */
class Chinese extends Person{
    private String name;
    private String sex;
    private int age;
    public int score;

    public Chinese(){}

    public Chinese(String name){
        this.name = name;
    }

    public Chinese(String name, String sex, int age){
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public void sayChina(){
        System.out.println("name:"+ name +" sayChina");
    }

    @Override
    public void sayHello() {
        System.out.println("name:"+ name +"sayHello");
    }

    public String getName() {
        return name;
    }

    public String getSex() {
        return sex;
    }

    public int getAge() {
        return age;
    }

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

    public void setSex(String sex) {
        this.sex = sex;
    }

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

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

3.1、通过一个对象获得完整的包名和类名

public void test(){
     /**
         * 通过一个对象获得完整的包名和类名
         */

        Class<?> chinese1 = null;
        Class<?> chinese2 = null;
        Class<?> chinese3 = null;

    	//方式一
        try {    
            chinese1 =  Class.forName("Reflect.Chinese");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    	
    	//方式二
        chinese2 = new Chinese().getClass();    //一般都用这种方法
		
    	//方式三
        chinese3 = Chinese.class;

        System.out.println(chinese1);
        System.out.println(chinese2);
        System.out.println(chinese3);
        System.out.println(chinese3.getName());

        //【运行结果】:
        //class Reflect.Chinese
        //class Reflect.Chinese
        //class Reflect.Chinese
        //Reflect.Chinese
}

3.2、获取其成员变量信息

public void test(){
    /**
         * 获取其成员变量信息
         */

       *Class<?> chinese4 = null;
        try {
            chinese4 = Class.forName("Reflect.Chinese");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //获取所有 公开 的成员变量,包括继承变量,只获取public 成员变量
        Field[] fields1 = chinese4.getFields();
        for (Field f : fields1) {
            System.out.println(f.getName());
        }
        System.out.println();
        //获取本类中的所有成员变量,包括私有成员变量
        Field[] fields2 = chinese4.getDeclaredFields();
        for (Field f: fields2) {
            System.out.println(f.getName());
        }
        //获取指定成员变量
        try {
            System.out.println(chinese4.getField("score"));
            System.out.println(chinese4.getDeclaredField("age"));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        //【运行结果】
        /*
        score
        name
        sex
        age
        score
        public int Reflect.Chinese.score
        private int Reflect.Chinese.age 
        */
}

3.3、获取构造方法信息

3.3.1、通过反射创建实例

通过反射创建实例的方法为Constructor的newInsta方法(原Class下的newInstance方法已过时)

public void test(){
    
         /**
         * 获取构造方法信息
         *
         * 通过反射创建实例的方法为Constructor的newInstance方法(原来的Class下的newInstance方法已过时)
         */
    
        Class<?> chinese5 = null;
        try {
            chinese5 = Class.forName("Reflect.Chinese");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //获取所有构造方法
        Constructor<?>[] constructors = chinese5.getConstructors();
        for (Constructor c: constructors) {
            System.out.println(c);
        }
        //获取某个公开的构造方法
        Constructor<?> constructor1 = null;
        Chinese chinese = null;
        try {
            constructor1 = chinese5.getConstructor(String.class);    //传入参数列表类型
            chinese = (Chinese) constructor1.newInstance("shuaibi");    //通过反射新建实例
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(constructor1);
        System.out.println(chinese);
        chinese.sayChina();


        //【运行结果】:
        //public Reflect.Chinese()
        //public Reflect.Chinese(java.lang.String,java.lang.String,int)
        //public Reflect.Chinese(java.lang.String)
        //public Reflect.Chinese(java.lang.String)
        //Chinese{name='shuaibi', sex='null', age=0}
        //name:shuaibisayChina


        //getDeclaredMethods()//获取本类定义的的方法,包括私有,不包括继承的方法
        //getDeclaredMethod(方法名,int.class,String.class)
        //此处省略代码
}

3.4、获取成员方法信息

这里省略代码,因为用法和获取构造方法信息一样

		//getMethods()//获取所有可见的方法,包括继承的方法
        //getMethod(方法名,参数类型列表)
        //getDeclaredMethods()//获取本类定义的的方法,包括私有,不包括继承的方法
        //getDeclaredMethod(方法名,int.class,String.class)

3.5、反射调用成员变量

public void test(){
    /**
         * 反射调用成员变量
         *
         */
        Class<?> chinese6 = null;
        try {
            //获取类对象
            chinese6 = Class.forName("Reflect.Chinese");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Field age = null;
        Field name = null;
        Field sex = null;
        try {
            //获取指定成员变量
             age = chinese6.getDeclaredField("age");
             name = chinese6.getDeclaredField("name");
             sex = chinese6.getDeclaredField("sex");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        //获取构造器对象,此处获取的是无参构造器
        Constructor<?> constructor = null;
        try {
            constructor = chinese6.getConstructor();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        //通过构造器对象创建实例
        Chinese instance = null;
        try{
            instance =(Chinese)constructor.newInstance();
        }catch(Exception e){
            e.printStackTrace();
        }



        //设置成员变量可访问
        age.setAccessible(true);
        name.setAccessible(true);
        sex.setAccessible(true);

        try {
            age.set(instance,18);
            name.set(instance,"张三");
            sex.set(instance,"男");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        System.out.println(instance);

        //【运行结果】Chinese{name='张三', sex='男', age=18}
}

3.6、反射调用成员方法

public void test(){
    /**
         * 反射调用成员方法
         */
        //获取类对象
        Class<?> chinese7 = null;
        try{
            chinese7 = Class.forName("Reflect.Chinese");
        }catch(Exception e)
        {
            e.printStackTrace();
        }
        //获取成员方法对象
        Method method = null;
        try{
            method = chinese7.getDeclaredMethod("sayChina");
        }catch(Exception e){
            e.printStackTrace();
        }
        //获取无参构造器对象
        //创建实例
        Constructor constructor = null;
        Chinese instance2 = null;
        try{
            constructor = chinese7.getConstructor(String.class);
            instance2 = (Chinese)constructor.newInstance("李四");
        }catch (Exception e){
            e.printStackTrace();
        }
        //使成员方法允许被调用
        method.setAccessible(true);
        try {
            method.invoke(instance2);
        }catch(Exception e){
            e.printStackTrace();
        }
    
        //【运行结果】name:李四 sayChina
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值