①. Java反射概述
1>.Java反射概述
- ①. Reflection(反射)是被视为
动态语言的关键
,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
- ②. 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息
我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看
到类的结构,所以,我们形象的称之为:反射
②. 获取Class的四种方法
2>.
Class类
1.Class类的概述
程序在经过javac.exe 命令以后,会生成一个或多个字节码文件(.class结尾),接着我们用java.exe 命令对某个字节码文件进行解释运行。将某个字节码文件加载到内存中。此过程称为类的加载。加载到内存中的类,我们就称为运行时类,此运行时类,就作为Class的一个实例
2.
四种获取Class类实例[ 掌握 ]
- ①. 调用运行时类的属性:
Class<Person>clazz1=Person.class;
- ②. 通过运行时类的对象,调用
getClass()
该方法是Object类中的方法,所有的Java对象都可以调用该方法
③. 调用Class的静态方法: forName(String classPath)
④. 使用类的加载器: ClassLoader[了解 ]
@Test public void fun1()throws Exception{ //方式一:调用运行时类的属性 //Class<Person>clazz1=Person.class; Class<Person>clazz1=Person.class; System.out.println(clazz1);//class itheima.com.Person //方式二:通过运行时类的对象,调用getClass() Person p1=new Person(); Class clazz2 = p1.getClass(); System.out.println(clazz2); //方式三: 调用Class的静态方法: forName(String classPath) Class clazz3=Class.forName("itheima.com.Person"); System.out.println(clazz3); //方式四:使用类的加载器: ClassLoader[了解 ] //ClassLoader classLoader2=new ReflectionDemo1().getClass().getClassLoader(); ClassLoader classLoader=ReflectionDemo1.class.getClassLoader(); Class clazz4=classLoader.loadClass("itheima.com.Person"); System.out.println(clazz4); }
哪些Class类并获取Class实例
1.class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
2.interface:接口
3.[ ]:数组
4.enum:枚举
5.annotation:注解@interface
6.primitive type:基本数据类型
7.void
③. ClassLoader
3>.
类加载器的介绍
①. JVM支持两种类型的类加载器,分别为引导类加载器(Bootstrap ClassLoader)和自定义类加载器(User-Defined ClassLoader)
②. 从概念上来讲,自定义类加载器一般指的是程序中由开发人员自定义的一类类加载器,但是Java虚拟机规范并没有这么定义,而是将所有派生于抽象类ClassLoader的类加载器都划分为自定义类加载器
③. sum.misc.Launcher:它是一个java虚拟机的入口应用
④. 无论类加载器的类型如何划分,在程序中我们常见的类加载器始终只有3个,如下所示:
@Test public void fun2(){ //对于自定义类,使用系统类加载器进行加载 ClassLoader classLoader = ReflectionDemo1.class.getClassLoader(); System.out.println(classLoader);//jdk.internal.loader.ClassLoaders$AppClassLoader@726f3b58 //调用系统类加载器getParent():获取扩展类加载器 ClassLoader classLoader1 = classLoader.getParent(); System.out.println(classLoader1);//$PlatformClassLoader@e73f9ac //调用扩展类加载器的getParent():无法获取引导类加载器 //引导类加载器主要负责java的核心类库,无法加载自定义类 ClassLoader classLoader2 = classLoader1.getParent(); System.out.println(classLoader2);//null }
@Test(使用ClassLoader加载配置文件) public void fun3()throws Exception{ //此时的文件默认在当前的moudule下 /* Properties prop=new Properties(); FileInputStream fis=new FileInputStream("a.properties");*/ // 读取配置文件的方式二: 使用classLoader //配置文件默认识别为:当前mouble的src下 ClassLoader classLoader=ReflectionDemo1.class.getClassLoader(); InputStream is=classLoader.getResourceAsStream("a.properties"); Properties prop=new Properties(); prop.load(is); String username=prop.getProperty("username"); System.out.println(username); }
①. 启动类加载器
1.启动类加载器(引导类加载器 Bootstrap ClassLoader)
①. 这个类加载使用C/C++语言实现的,嵌套在JVM内部
②. 它用来加载Java的核心类库(JAVA_HOME/jre/lib/rt.jar、resource.jar或sum.boot.class.path路径下的内容),用于提供JVM自身需要的类
③. 并不继承自java.lang.ClassLoader,没有父加载器
④. 加载扩展类和应用程序类加载器,并指定为他们的父类加载器
⑤. 由于安全考虑,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类
②. 扩展类加载器(Extension ClassLoader)
2.扩展类加载器
①. Java语言编写,由sum.music.Launcher$ExtClassLoader实现
②. 派生于ClassLoader类
③.父类加载器为启动类加载器
④.从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的jre/lib/ext子目录(扩展目录)下加载类库。如果用户创建的JAR放在此目录下,也贵自动由扩展类加载器加载
③. 应用程序类加载器(系统类加载器)
3.应用程序类加载器(系统类加载器 AppClassLoader)
①. java语言编写,由sum.misc.Launcher$AppClassLoader实现
②. 派生于ClassLoader类
③. 父类加载器为扩展类加载器
④. 它负责加载环境变量classpath或系统属性java.class.path指定路径下的类库
⑤.该类加载是程序中默认的类加载器,一般来说,Java应用的类都是由它来完成加载
⑥. 通过ClassLoader#getSystemClassLoader()方法可以获取到该类加载器