反射的基本概念
Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
Java反射机制提供的功能
-
在运行时判断任意一个对象所属的类
-
在运行时构造任意一个类的对象
-
在运行时判断任意一个类所具有的成员变量和方法
-
在运行时调用任意一个对象的成员变量和方法
-
生成动态代理
反射相关的主要API
-
java.lang.Class: 代表一个类
-
java.lang.reflect.Method: 代表类的方法
-
java.lang.reflect.Field: 代表类的成员变量
-
java.lang.reflect.Constructor: 代表类的构造方法
常用的反射方法
- 前提:若已知具体的类,通过类的class属性获取,该方法
最为安全可靠,程序性能最高
实例:Class clazz = String.class; - 前提:已知某个类的实例,调用该实例的getClass()方法获
取Class对象
实例:Class clazz = “www.kkb.com”.getClass(); - 前提:已知一个类的全类名,且该类在类路径下,可通过
Class类的静态方法forName()获取,可能抛出ClassNotFoundException
实例:Class clazz = Class.forName(“java.lang.String”);
类的加载过程
当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化。
了解ClassLoader
类加载器是用来把类(class)装载进内存的。JVM 规范定义了两种类型的类加载器:启动类加载器(bootstrap)和用户自定 义加载器(user-defined class loader)。 JVM在运行时会产生 3个类加载器组成的初始化加载器层次结构 ,如下图所示
反射的使用
通过Class类来实现:
package day18;
import static org.junit.Assert.*;
import org.junit.Test;
public class PersonTest {
//没有反射概念之前我们如何使用对象
@Test
public void test01() throws Exception {
Person person = new Person();
person.name = "zhangsan";
person.age = 18;
person.show();
System.out.println(person);
}
//通过反射,得到我们Person对象
@Test
public void test02() throws Exception {
Class c = Person.class;
Person person = (Person)c.newInstance();
person.show();
System.out.println(person);
}
@Test
public void test03() throws Exception {
//第一种
Class c1 = String.class;
System.out.println(c1.getName());
Class P1 = Person.class;
System.out.println(P1.getName());
//第二种
Class class1 = "c".getClass();
System.out.println(class1.getName());
//第三种
Class class2 = Class.forName("day18.Person");
System.out.println(class2.getName());
}
}
/**
java.lang.String
day18.Person
java.lang.String
day18.Person
*/
难道没有无参的构造器就不能创建对象了吗?
不是!只要在操作的时候明确的调用类中的构造方法,并将参数传递进去
之后,才可以实例化操作。步骤如下:
1)通过Class类的getDeclaredConstructor(Class … parameterTypes) 取得本类的指定形参类型的构造器
2)向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数。
3)通过Constructor实例化对象。
下面我们来举一个例子:
我们的Person类构造如下:
package day18;
public class Person {
public String name;
public int age;
public Person() {
}
public Person(int age,String name) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public void show() {
System.out.println(name +","+ age );
}
}
随后我们通过反射的方式,来通过有参构造和无参构造来实现实例化:
@Test
public void test04() throws Exception {
//第一种必须有参数,并且注意构造器权限
Class class1 = Person.class;
Person person = (Person)class1.newInstance();
}
@Test
public void test05() throws Exception {
//方法二,使用其他构造方法
Class class1 = Person.class;
Constructor c1 = class1.getDeclaredConstructor( int.class , String.class );
Person person = (Person)c1.newInstance(18,"Jeason");
System.out.println(person);
}
/*
Person [name=Jeason, age=18]
*/