反射(反射的介绍、获取源头Class、创建对象、属性和方法)

一、 反射的介绍

1.反射的定义

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
Java反射机制,可以实现以下功能:
①在运行时判断任意一个对象所属的类;
②在运行时构造任意一个类的对象;
③在运行时判断任意一个类所具有的成员变量和方法;
④在运行时调用任意一个对象的方法;
⑤生成动态代理;

二、获取源头Class(重点)

所有类的对象其实都是Class的实例。这个 Class 实例可以理解为类的模子,就是包含了类的结构信息,类似于图纸。我们日常生活中,需要创造一个产品,如想山寨一个iphone手机,怎么办?
有三种方式可以实现:
⑴买个iphone手机,拆的七零八落的,开始山寨;
⑵到iphone工厂参观,拿到iphone磨具,开始山寨;
⑶跑到美国盗取iphone的图纸,开始山寨,最后一种最暴力,最爽。
同理,获取类的Class对象也有三种方式
⑴Class.forName(”包名.类名”) //一般尽量采用该形式
(2)类.class
(3)对象.getClass()
思考:目前我们创建对象的方式有哪写?

[1]获取Class对象

Class是一切的源头,所有伟大的事业都有一个不起眼的开头。而反射有三种出场方式
第一种方式: 对象.class

		Person person = new Person();
        //对象.getClass()
        Class<? extends Person> aClass = person.getClass();
        System.out.println(aClass.getName());

第二种方式: 类.class

		//类名.class
        Class<Person> aClass = Person.class;

第三种方式(推荐方式): Class.forName()

// Class.forName("全限定路径")  全限定路径:包名+类名
Class<?> aClass = Class.forName("com.shsxt.reflect.Person");

有了class对象,我们就有了一切,这就是反射的源头,接下来就是“庖丁解牛”。

[2] 获取修饰符

获取修饰符,使用 getModifiers() 即可, Modifier 类提供了 static 方法和
常量来解码类和成员访问修饰符
在这里插入图片描述

		Class<Person> aClass = (Class<Person>) Class.forName("com.shsxt.reflect.Person");
        int modifiers = aClass.getModifiers();
        //使用Modifier转换为相应的字符串
        System.out.println(Modifier.toString(modifiers));

在这里插入图片描述

三、创建对象

1. 构造器

根据Class对象,我们可以获得构造器,为实例化对象做准备。调用以下api即可。
在这里插入图片描述

ConstructorgetDeclaredConstructor([参数列表.class]) 返回一个Constructor对象,这个构造器是父类或子类的共有的构造器
Constructor<?>[]getDeclaredConstructors()返回包含一个数组Constructor对象反射,这个构造器对象是自己的公有和私有的构造器

私有的属性、构造器、方法均可通过调研setAccessible(true)来打开权限。

	 	//获取Person的class
	 	Class<Person> personClass = Person.class;
        //不能获取私有的构造器,只能获取公开的构造器
        Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor);
        Person person = constructor.newInstance("张三", 18);
        System.out.println(person);
        //可以获取私有的构造器,也可以获取公开的构造器
        Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor();
        System.out.println(declaredConstructor);
        //如果是私有的,则打开权限再使用
        declaredConstructor.setAccessible(true);
        System.out.println(declaredConstructor.newInstance());

        //获取所有的公有的构造器
        Constructor<?>[] constructors = personClass.getConstructors();
        System.out.println(constructors.length);
        //获取所有的构造器  公有+私有
        Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
        System.out.println(declaredConstructors.length);

2.实例化对象

创建对象的方式,有new克隆反序列化,再加一种,根据Class对象,使用newInstance() 或者构造器实例化对象。调用以下api即可

// 通过反射
//   clz newInstance()
//     通过获取构造器, 利用构造器去创建对象
public class NewInstance {
    public static void main(String[] args) throws Exception {
        //1、获取Class
        Class<Person> aClass = (Class<Person>)Class.forName("com.shsxt.reflect.Person");
        //2、创建对象,必须保证空构造存在.而且只能是调用空构造,属性是没有数据的
        //(一)创建对象的方式一:
        Person person = aClass.newInstance();
        System.out.println(person);

        // (二)创建对象方式二:无参
        // 获取构造器对象(无参构造)
        Constructor<Person> constructor = aClass.getConstructor();
        //执行构造器,获取Bean对象
        Person person1 = constructor.newInstance();
        System.out.println(person1);

        // (二)创建对象方式三:有参  获取指定构造器  获取带参构造  String类型,  int类型
        Constructor<Person> constructor1 = aClass.getConstructor(String.class, int.class);
        Person person2 = constructor1.newInstance("张三", 18);
        System.out.println(person2);
        //(三)创建对象的方式四:通过私有构造器创建
        // 获取私有的构造器
        Constructor<Person> declaredConstructor = aClass.getDeclaredConstructor();
        //打开权限
        declaredConstructor.setAccessible(true);
        Person person3 = declaredConstructor.newInstance();
        System.out.println(person3);
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
    }
}

在这里插入图片描述
注意:newInstance()是调用空构造如果空构造不存在,会出现异常。由此可知,使用其他构造器创建对象比较麻烦,使用空构造非常简单。确保空构造存在

3. 父类与接口

在这里插入图片描述
定义Person类,Student类继承Person类

		 //获取Student的Class
        Class<Student> studentClass = Student.class;
        //student的父类
        Class<? super Student> superclass = studentClass.getSuperclass();
        System.out.println(superclass);

在这里插入图片描述

四、属性和方法

1. 属性(获得属性及设置属性值)

获取所有属性(包括父类或接口) ,使用 Field 即可操作, Field 作为描述属性的对象
在这里插入图片描述

/**
Class
属性的操作: Field对象
 */
public class ReflectField {
    public static void main(String[] args) throws Exception {
        //获取Class对象
        Class<Student> aClass = Student.class;
        Student student = aClass.newInstance();

        Field id = aClass.getField("id");
        // 属性的权限, 类型, 名称
        // 通过id对象获取 studnet对象的 id属性值
        int idValue = (int)id.get(student);  // 获取某个对象的这个属性的值
        System.out.println(idValue);//10
        //要获取一个对象的属性值
        Field money = aClass.getDeclaredField("money");
        // 如果是私有属性则打开权限
        money.setAccessible(true);
        //获取指定对象的属性
        System.out.println(money.get(student));//100
        //修改一个对象的属性值
        money.set(student,2999);
        System.out.println(student.getMoney());//2999
        //获取money属性的类型
        System.out.println(money.getType());//int
        System.out.println(Modifier.toString(money.getModifiers()));//private
        //获取属性名称
        System.out.println(money.getName());//money
        //获取静态属性scoolName
        Field scoolName = aClass.getField("scoolName");
        // 静态的内容 尽量不要和对象关联  对象参数设为null
        scoolName.set(null,"sxt");
        System.out.println(Student.scoolName);//sxt
    }
}

2.方法(通过反射执行方法)

获取所有方法(包括父类或接口),使用 Method 即可。 Method 即作为描述方法的对象。
在这里插入图片描述
实体类Person,Student的父类

public class Person {
    private String name;
    private int age;

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

    public Person() {
    }

    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 void testFatherPublict(){
        System.out.println("Person.testFatherPublict");
    }

    private void testFatherPrivate(){
        System.out.println("Person.testFatherPrivate");
    }

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

实体类Student

public class Student extends Person{
    public int id;
    private int money;
    public static String scoolName;
    public Student() {
        this.id = 10;
        this.money = 100;
    }
    public Student(int id, int money) {
        this.id = id;
        this.money = money;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getMoney() {
        return money;
    }
    public void test(String str){
        System.out.println(str);
    }
    public void setMoney(int money) {
        this.money = money;
    }
    public void testSelefPublic(){
        System.out.println("Student.testSelefPublic");
    }
    private void testSelefPrivate(){
        System.out.println("Student.testSelefPrivate");
    }
   @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", money=" + money +
                '}';
    }
}
 //获取Class对象
        Class<Student> studentClass = Student.class;
        Student student = studentClass.newInstance();

        //获取方法  方法的对象
        //方法名  、参数类型.class
        Method method = studentClass.getMethod("test", String.class);
        System.out.println(method);

        //执行方法
        // 通过student执行它的 m1对象中的方法, 将 "helloworld" 作为实参,执行这个方法得到的结果, invoke的返回值
        Object o = method.invoke(student, "helloworld");
        //System.out.println(o);
        //获取返回值
        Class<?> type = method.getReturnType();
        System.out.println(type);

        Method method1 = studentClass.getDeclaredMethod("testSelefPrivate");
        //打开方法的权限
        method1.setAccessible(true);
        method1.invoke(student);

通过反射获取方法

 //获取Class对象
        Class<Student> studentClass = Student.class;
        Student student = studentClass.newInstance();

        //获取方法  方法的对象
        //方法名  、参数类型.class
        Method method = studentClass.getMethod("test", String.class);
        System.out.println(method);

        //执行方法
        // 通过student执行它的 m1对象中的方法, 将 "helloworld" 作为实参,执行这个方法得到的结果, invoke的返回值
        Object o = method.invoke(student, "helloworld");
        //System.out.println(o);
        //获取返回值
        Class<?> type = method.getReturnType();
        System.out.println(type);

        Method method1 = studentClass.getDeclaredMethod("testSelefPrivate");
        //打开方法的权限
        method1.setAccessible(true);
        method1.invoke(student);

在这里插入图片描述

五、数组(仅了解)

操作数组需要借助Array类

//1、创建数组 
Object obj = Array.newInstance(int.class, 5); 
//2、获取大小 
if(obj.getClass().isArray()){ 
    //3、判断是否为数组 
    System.out.println(Array.getLength(obj)); 
    //4、设置值 
    Array.set(obj,0, 100); 
    //5、获取值 
    System.out.println(Array.get(obj,0));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值