【Java基础9】反射

反射

主要部分

1.理解反射的机制,为什么java语言中会有反射,为什么会有反射的概念。

2.反射中class对象的常见方法的基本使用。

3.熟悉和理解反射在java中的重要应用场景。

一.概念题

  1. 反射的概念。

    Reflection(反射),是java被视为动态语言的关键,反射机制允许程序在执行期间借助于Reflection API 取得任何类的内部信息,并能直接操作任何对象的内部属性及其方法。

  2. 了解反射产生的原因,并简要概述。

    Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。而通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

    用途:

    1、反编译:.class–>.java

    2、通过反射机制访问java对象的属性,方法,构造方法等

    3、当我们在使用IDE,比如Ecplise时,当我们输入一个对象或者类,并想调用他的属性和方法时,一按点号,编译器就会自动列出他的属性或者方法,这里就是用到反射。

    4、反射最重要的用途就是开发各种通用框架。比如很多框架(Spring)都是配置化的(比如通过XML文件配置Bean),为了保证框架的通用性,他们可能需要根据配置文件加载不同的类或者对象,调用不同的方法,这个时候就必须使用到反射,在运行时动态加载需要的加载的对象。

  3. 反射的机制,简要概述反射机制在创建对象的原理。

    加载完类之后,在堆内存放的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象)这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像是一面镜子,透过这面镜子看到类的结构,所以,我们形象的称之为:反射

    正常方式:引入需要的包类名称---->通过new实例化---->取得实例化对象

    反射方式:实例化对象---->getClass()方法----->得到完整的包类名称

二.编程题

编写一个student类,通过反射机制获取其实例并将实例对象中的所有数据输出到student.txt文件中,

源码中创建student类的对象时不允许通过new关键字创建对象。

public class demo01 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获得一个对象
        Class c1 = Class.forName("java0019.Student");
        //通过构造器创建对象
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        Student s1 = (Student) declaredConstructor.newInstance("小明", 001, 18);
        try {
            // 创建一个打印输出流,输出的目标为"F:\\QQGG\\Student.txt"
            PrintStream f1 = new PrintStream("F:\\QQGG\\Student.txt");
            //把创建的打印输出流赋给系统,向f1输出
            System.setOut(f1);
            System.out.println(s1.getName()+","+s1.getId()+","+s1.getAge());
            f1.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class Student {
        private String name;
        private int id;
        private int age;

        public Student() {
        }

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

        public String getName() {
            return name;
        }

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

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public int getAge() {
            return age;
        }

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

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

三.挑战题

将上述问题改写,不允许出现任何类中任何的原方法在main函数中,只能使用反射包中的方法完成对对象的创建和操作,同时完成操作。

public class demo01 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获得一个对象
        Class c1 = Class.forName("java0019.Student");
        //通过构造器创建对象
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        Student s1 = (Student) declaredConstructor.newInstance("小明", 001, 18);
        try {
            // 创建一个打印输出流,输出的目标为"F:\\QQGG\\Student.txt"
            PrintStream f1 = new PrintStream("F:\\QQGG\\Student.txt");
            //把创建的打印输出流赋给系统,向f1输出
            System.setOut(f1);
            System.out.println(s1.toString());
            f1.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class Student {
        private String name;
        private int id;
        private int age;

        public Student() {
        }

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

        public String getName() {
            return name;
        }

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

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public int getAge() {
            return age;
        }

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

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

### 补充:
反射机制:
加载完类之后,在堆内存放的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象)这个对象就包含了完整的类的结构信息。
我们可以通过这个对象看到类的结构。这个对象就像是一面镜子,透过这面镜子看到类的结构,所以我们形象地称之为:反射

反射机制在创建对象的原理:
正常方式:引入需要的包类名称---->通过new实例化---->取得实例化对象
反射方式:实例化对象---->getClass()方法----->得到完整的包类名称


反射应用
    Java反射机制主要提供了以下功能:
    在运行时判断任意一个对象所属的类;
    在运行时构造任意一个类的对象;
    在运行时判断任意一个类所具有的成员变量和方法;
    在运行时调用任意一个对象的方法;
    生成动态代理。


用途:

1、反编译:.class-->.java
2、通过反射机制访问java对象的属性,方法,构造方法等
3、当我们在使用IDE,比如Ecplise时,当我们输入一个对象或者类,并想调用他的属性和方法时,一按点号,编译器就会自动列出他的属性或者方法,这里就是用到反射。
4、反射最重要的用途就是开发各种通用框架。比如很多框架(Spring)都是配置化的(比如通过XML文件配置Bean),为了保证框架的通用性,他们可能需要根据配置文件加载不同的类或者对象,调用不同的方法,这个时候就必须使用到反射,在运行时动态加载需要的加载的对象。


--------------------------------------------------------------------------------
java.lang.class :代表整个字节码文件,代表一个类型
java.lang.reflect.Method :代表字节码中的方法字节码
java.lang.reflect.Constructor :代表字节码中的构造方法字节码
java.lang.reflect.Field :代表字节码中的属性字节码

获取java.lang.Class实例的三种方式
方式一:Class c = Class.forName(“完整类名带包名”);
方式二:Class c = 引用getClass();
方式三:Class c = 任何类型.class
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值