Java 反射

Java 反射

关于java.lang.Class类的理解

  • 类的加载过程

代码经过javac.exe命令之后 会生成一个或多个字节码文件(.class结尾)

接着我们使用java.exe命令对某个字节码进行解释运行 相当于某个字节码文件加载到内存中 此过程叫做类的加载 加载到内存中的类 我们叫做运行时类 此运行时类 即叫做Class的一个实例

  • 换句话说 Class实例对应着一个运行时类

我们来看一下获取Class实例的几种方式

package com.zyk;

public class ReflectionTest {
    public static void main(String[] args) throws ClassNotFoundException {
        //调用运行时类的属性 .class
        Class clazz1=Person.class;
        System.out.println(clazz1);
        //调用运行时类的对象
        Person person=new Person();
        Class clazz2=person.getClass();
        System.out.println(clazz2);
        //调用Class的静态方法
        Class clazz3=Class.forName("com.zyk.Person");
        System.out.println(clazz3);
        //使用类的加载器
       ClassLoader classLoader= ReflectionTest.class.getClassLoader();
       Class clazz4=classLoader.loadClass("com.zyk.Person");
        System.out.println(clazz4);
    }
}

结果

class com.zyk.Person
class com.zyk.Person
class com.zyk.Person
class com.zyk.Person

了解类的加载器 ClassLoader

在这里插入图片描述

Java把加载动作放到JVM外部实现,以便让应用程序决定如何获取所需的类,JVM提供了3种类加载器,启动类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)、应用程序类加载器(Application ClassLoader)

我们看一个代码案例

package com.zyk;

public class ClassLoaderTest {
    public static void main(String[] args) {
        //对于自定义类 使用应用类加载器加载
        ClassLoader classLoader1 = ClassLoaderTest.class.getClassLoader();
        System.out.println(classLoader1);
        //调用getParent 获取扩展类加载器
        ClassLoader classLoader2 = classLoader1.getParent();
        System.out.println(classLoader2);
        //获取启动类加载器 只不过显示不出来
        //启动类加载器主要负责加载Java的核心类库 比如String
        ClassLoader classLoader3 = classLoader2.getParent();
        System.out.println(classLoader3);
    }
}

结果

sun.misc.Launcher$AppClassLoader@18b4aac2//应用类加载器
sun.misc.Launcher$ExtClassLoader@1540e19d//扩展类加载器
null//启动加载器

通过反射创建运行时类的对象

package com.zyk;

public class NewInstanceTest {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        Class<Person> personClass = Person.class;
        Person person = personClass.newInstance();
        System.out.println(person);
    }
}

结果

Person{id=0, name='null'}

注意

运行时类必须提供空参的构造器 后期框架中 便于利用反射创建运行时类的对象

体会反射的动态性

package com.zyk;

import java.util.Random;

public class Test {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        for (int i = 0; i <10 ; i++) {
            //生成随机数
            int num=new Random().nextInt(3);
            String path="";
            switch (num){
                case 0:
                    path="com.zyk.Person";
                    break;
                case 1:
                    path="java.util.Date";
                    break;
                case 2:
                    path="java.lang.Object";
                    break;
            }
            Object o=getInstance(path);
            System.out.println(o);
        }

    }
    public static Object getInstance(String path) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class clazz = Class.forName(path);
        Object obj= clazz.newInstance();
        return obj;
    }
}

结果

Person{id=0, name='null'}
Person{id=0, name='null'}
Fri Apr 10 14:51:55 CST 2020
Fri Apr 10 14:51:55 CST 2020
java.lang.Object@135fbaa4
Person{id=0, name='null'}
java.lang.Object@45ee12a7
java.lang.Object@330bedb4
Fri Apr 10 14:51:55 CST 2020
java.lang.Object@2503dbd3

通过上面的例子 我们看出 只有在运行的时候 我们才能决定要去创建哪个对象 这就是反射的动态性的体现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值