文章目录
一、什么是反射?
Java 的反射机制,就是在运行状态中,
- 对于任意一个类,都能够知道它的所有属性和方法;
- 对于任意一个对象,都能够调用它的任意一个属性和方法;
这种动态获取信息以及动态调用对象方法的功能称为 Java 的反射机制。
Tips:
反射就是把 Java 类中的各种成分(成员变量、方法、构造方法等)映射成一个个的 Java 对象。
二、反射的基本功能
- 在运行时构造任意一个类的对象;
- 在运行时判断任意一个类所具有的成员变量和方法;
- 在运行时判断任意一个对象所属的类;
- 在运行时调用任意一个对象的方法;
- 生成动态代理。
三、反射的使用
反射的实现主要借助四个类:Class、Constructor、Field 和 Method。Class 类位于 java.lang 包下,Constructor、Field 和 Method 类位于 java.lang.reflect 包下。从类名就能知道它们的功能:Class 类用来获取类对象、Constructor 用来获取构造方法、Field 类用来获取类中的属性、Method 类用来获取类的方法。
1、通过 Class 类获取类对象
三种方式:
(1)通过实例对象获得:Class<?> class = object.getClass();
(2)任何数据类型(包括基本数据类型)都有一个“静态”的 class 属性,通过类名获得 Class<?> class = 类名.class;
(3)通过类名的相对路径(即 包名.类名)获得:Class<?> class = Class.forName(“包名.类名”);
创建一个 Star 类用来测试。
package reflect_Test;
public class Star {
}
测试如下:
package reflect_Test;
public class reflectTest {
public static void main(String[] args) {
// (1)通过实例对象获取 Class 对象:
Star star = new Star();
Class starClass1 = star.getClass();
// getName() 是 Class 类的一个方法,返回对象的类名
System.out.println(starClass1.getName());
// (2)通过类名获取 Class 对象,类的 class 属性:
Class starClass2 = Star.class;
System.out.println(starClass2.getName());
// (3)通过类名的相对路径获取 Class 对象:
try {
// 括号里的字符串是类的相对路径,即 包名.类名
Class starClass3 = Class.forName("reflect_Test.Star");
System.out.println(starClass3.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
测试结果:
reflect_Test.Star
reflect_Test.Star
reflect_Test.Star
注意:
1、在运行期间,一个类,只有一个类对象产生。
2、第三种方式是最常用的。 第一种方式,已经有对象了,就不用反射了;第二种需要导入类的包,依赖性太强,不导包就抛编译错误(上面的例子,Star 类和 reflectTest 类在同一个包下,不用导包);第三种方式最常用,知道类的路径就可以了。
2、通过 Constructor 类获取类的构造方法
给 Star 类添加构造方法:
package reflect_Test;
public class Star {
// 默认的构造方法(默认构造方法的访问修饰符继承自类的访问修饰符)
Star(boolean b){
System.out.println(b);
}
// 无参的构造方法
public Star(){}
// 有参的构造方法
public Star(String name, int number){
System.out.println(name +" = " + number);
}
// 私有的构造方法
private Star(String name){
System.out.println(name);
}
// 受保护的构造方法
protected Star(int number){
System.out.println(number);
}
}
测试代码:
package reflect_Test;
import java.lang.reflect.Constructor;
public class constructorTest {
public static void main(String[] args) throws Exception {
// 加载类对象
Class sClass = Class.forName("reflect_Test.Star");
// 1、获取所有的构造方法(默认的、公共的、受保护的、私有的):
System.out.println("1、所有的构造方法:");
Constructor[] array1 = sClass.getDeclaredConstructors();
for(Constructor c : array1){
System.out.println(c);
}
// 2、获取所有公共的构造方法:
System.out.println("2、所有公共的构造方法:");
Constructor[] array2 = sClass.getConstructors();
for(Constructor c : array2){
System.out.println(c);
}
// 3、获取公共、无参的构造方法:
System.out.println("3、公共、无参的构造方法:");
Constructor con = sClass.getConstructor();
System.out.println(con);
// 可以用得到的构造方法new一个Star实例,调用Constructor类的newInstance()方法
Object o = con.newInstance();
Star s = (Star)o;// 要转换类型
// 4、获取指定参数类型的构造方法:
// getDeclaredConstructor(Class<?>... parameterTypes)方法可以指定参数类型,
// 该方法返回和指定参数类型相符的构造方法
System.out.println("4、指定参数类型的构造方法:");
Constructor con1 = sClass.getDeclaredConstructor(String.class);
System.out.println(con1);
}
}
测试结果:
1、所有的构造方法:
protected reflect_Test.Star(int)
private reflect_Test.Star(java.lang.String)
public reflect_Test.Star(java.lang.String,int)
public reflect_Test.Star()
reflect_Test.Star(boolean)
2、所有公共的构造方法:
public reflect_Test.Star(java.lang.String,int)
public reflect_Test.Star()
3、公共、无参的构造方法:
public reflect_Test.Star()
4、指定参数类型的构造方法:
private reflect_Test.Star(java.lang.String)
3、通过 Field 类获取成员变量
Field 类的使用方法和 Constructor 类是类似的。图片来自 Java API。
4、通过 Method 类获取成员方法
Method 类的使用方法和 Constructor 类是类似的。图片来自 Java API。