一、Class类
1. 对象照镜子后可以得到的信息:某个类的数据成员名、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE都为其保留一个不变的Class类型的对象。一个Class对象包含了特定某个类的有关信息。
2. Class对象只能由系统建立对象
3. 一个类在JVM中只会有一个Class实例
4. 每个类的实例都会记得自己是由哪个Class实例所生成
二、获取Class对象的方式
1. 通过类的class属性获取,该方法最为安全可靠,程序性能更高。
Class clazz = String.class;
2. 通过对象的getClass()方法获取
Person person = new Person();
Class clazz = person.getClass();
3. 通过Class对象的forName()静态方法获取,但可能抛出ClassNotFoundException异常
Class clazz = Class.forName("java.lang.String");
三、Class类的常用方法
方法名 | 功能说明 |
---|---|
static Class forName(String name) | 返回指定类名name的Class对象 |
Object newInstance() | 调用缺省构造函数,返回该Class对象的一个实例 |
Object newInstance(Object[] args) | 调用当前格式构造函数,返回该Class对象的一个实例 |
getName() | 返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称 |
Class getSuperClass() | 返回当前Class对象的父类的Class对象 |
Class[] getInterfaces() | 获取当前Class对象的接口 |
ClassLoader getClassLoader() | 返回该类的类加载器 |
Class getSuperclass() | 返回表示此Class所表示的实体的超类的Class |
四、ClassLoader类加载器
类加载器是用来把类(class)装载进JVM的。JVM规范定义了两种类型的类装载器:启动类装载器(bootstrap)和用户自定义装载器(user - defined class loader)。JVM在运行时会产生3个类加载器组成的初始化加载器层次结构,如下图所示:
五、示例代码
package test.com.atguigu.javase.lesson12;
import com.atguigu.javase.lesson12.Person;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.lang.reflect.Field;
public class ReflectionTestTest {
/**
* 关于Class******
* 1. Class是一个类
* 2. 对象照镜子后可以得到的信息,某个类的数据名、方法和构造器、某各类到底实现了哪些接口、继承了哪些父类。
* 3. 对于每个类而言,JRE都为其保留一个不变的Class类型的对象。
* 一个Class对象包含了特定某个类的有关信息
* 4. Class对象只能由系统建立对象
* 5. 一个类在JVM中只会有一个Class实例
* 6. 最大的作用,只有一个类的全类名,而没有这个类的对象,依然可以得到该类的基本信息
*/
@Test
public void testClass() throws ClassNotFoundException {
//1.得到Class对象*****
//1.1 直接通过类名.class的方式得到
Class clazz1 = null;
clazz1 = Person.class;
Field[] fields = clazz1.getDeclaredFields();
//1.2 通过对象调用getClass()方法来获取
Person person = new Person();
Class clazz2 = null;
clazz2 = person.getClass();
//1.3 通过全类名的方式获取,用的较多*****
String className = "com.atguigu.javase.lesson12.Person";
Class clazz3 = null;
clazz3 = Class.forName(className);
System.out.println();
}
/**
* Class类的newInstance()方法*****
* 通过全类名反射得到Class类的一个对象clazz,然后在创建一个实例
*/
@Test
public void testNewInstance() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
String className = "com.atguigu.javase.lesson12.Person";
Class clazz = Class.forName(className);
//利用Class对象的newInstance()方法来创建类的一个对象
//实际调用的是类的 无参数 的构造器
//一般的,一个类若声明了带参数的构造器,也要声明一个无参数的构造器
Object object = clazz.newInstance();
System.out.println(object);
}
@Test
public void testClassLoader() throws ClassNotFoundException, FileNotFoundException {
//1. 获取一个系统的类加载器
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
System.out.println(classLoader);
//2.获取系统类加载器的父类加载器扩展类加载器
classLoader = classLoader.getParent();
System.out.println(classLoader);
//3. 获取扩展类加载器的父类加载器引导类加载器
classLoader = classLoader.getParent();
System.out.println(classLoader);
//4.测试当前类由哪个类加载器进行加载:
classLoader =
Class.forName("test.com.atguigu.javase.lesson12.ReflectionTestTest")
.getClassLoader();
System.out.println(classLoader);
//5.测试jdk提供的Object类由哪个类加载器负责加载
classLoader = Class.forName("java.lang.Object").getClassLoader();
System.out.println(classLoader);
//6. ****关于类加载器的一个主要方法
//调用getResourceAsStream获取类路径下的文件对应的输入流。
//此处报错,若放在项目目录下可以得到。src下放的test.properties被自动的放在bin目录下。
//系统类加载器能加载src对应的bin目录下对应的.class
//InputStream in = new FileInputStream("test.properties");//报错
//系统类加载器可以类路径下所有类,也可以加载类路径下所有文件。
InputStream in = null;
in = this.getClass().getClassLoader().getResourceAsStream("test.properties");
System.out.println(in);
}
}