反射
概述
- 反射是Java系统的API 它允许程序在运行过程
- 取得任何一个已知名称的类的内部信息,包括其中的构造方法,声明的字段和定义的方法等
- 利用反射API可以实现动态执行
- 动态加载类,获取信息
- 动态创建对象
- 动态访问属性
- 动态调用方法 - 动态执行 :只是在JVM运行期间才确定的执行次序
- 静态执行:是指编译以后就确定了程序的运行次序,JVM运行期间按照既定的次序执行
反射API
Java反射API提供了动态执行能力
Class API:java.lang.Class,用于加载类和获取类的相关信息
Java反射API位于java.lang.reflect包中。主要包含以下几类:
- Constructor类:用来描述一个类的构造方法
- Field类:用来描述一个类的成员变量
- Method类:用来描述一个类的方法
- Modifier类:用来描述类内各元素的修饰符
- Array:用来对数组进行操作
反射机制
java反射机制
反射是一种动态机制,允许我们实例化对象,调用方法,操作属性从编码期间确定转移到程序运行期确定。
因此反射提高了程序的灵活度,但是随之带来的是更多的系统开销和较慢的运行效率,因此反射机制不能过度的使用 。
获取利用反射操作的类的对象
- Class实例:
JVM中每个被加载的类都有且只有一个Class的实例与之对应,通过类对象(Class的实例)我们可以得知其表示的类的一切信息,例如:类名,有哪些属性,哪些方法,哪些构造器等等,并利用这些方法在程序运行期间操作它们。
获取一个类的类对象有三种方式: - 类名.class
例如:Class cls = String.class;
Class cls = int.class; - Class.forName(String className)
例如:Class cls =Class.forName(“java.lang.String”);
这里forName方法中传入的是类的完全限定名,格式为:包名. 类名 - 类加载器ClassLoader运行加载并获取
优点:简单,直接 缺点:硬编码获取,不灵活 - 获取所有公开方法
Method[] methods = cls.getMethods(); - 获取到本类自己定义的方法,包括私有方法
Method[] methods = cls.getDeclaredMethods();
上述代码:
try {
// Class cls = Class.forName("java.util.HashMap");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个类名:");
String className = scanner.nextLine();
Class cls = Class.forName(className);
String name = cls.getName();
System.out.println(name);
//获取String中所有公开方法
// Method[] methods = cls.getMethods();
//获取到本类自己定义的方法,包括私有方法
Method[] methods = cls.getDeclaredMethods();
for(Method method : methods) {
System.out.println(method.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
利用反射进行实例化操作
new关键字
Person p = new Person();
System.out.println(p);
利用反射实例化
(1)加载类的类对象
Class cls = Class.forName("reflect.Person");
Object o = cls.newInstance();//必须有无参构造器
System.out.println(o);
(2)利用反射调用私有成员
Person p = new Person();
// p.dosome();编译不通过
Class<?> cls = Class.forName("reflect.Person");
Object o = cls.newInstance();
//获取Person中的私有方法dosome
Method m = cls.getDeclaredMethod("dosome");
m.setAccessible(true);
m.invoke(o);
(3)通过指定的构造器实例化对象
Person p = new Person();
System.out.println(p);
Person p1 = new Person("李四",55);
System.out.println(p1);
Class<?> cls = Class.forName("reflect.Person");
//获取构造器(无参构造器)
Constructor<?> c = cls.getConstructor();
//利用该构造器实例化对象
Object o = c.newInstance();
System.out.println(o);
//利用Person(String,int)
Constructor<?> c2 = cls.getConstructor(String.class,int.class);
//实例化
Object o2 = c2.newInstance("西瓜",18);
System.out.println(o2);
(4)使用反射机制调用方法
Person p = new Person();
p.sayHello();
Scanner scanner = new Scanner(System.in);
System.out.println("请输入类名:");
String className = scanner.nextLine();
System.out.println("请输入方法名:");
String methodName = scanner.nextLine();
//实例化
Class<?> c = Class.forName(className);
Object o = c.newInstance();//Person o = new Person();
//获取sayHello方法并调用
Method m = c.getMethod(methodName);
//Method提供了一个动态执行一个方法的方法:Object invoke(Object obj,Object..args)
m.invoke(o);//o.sayHello();
System.out.println("aaaaaaaaaaaaaaaaaaaaaaaa");
(5)调用有参方法
Person p = new Person();
p.sayHello("大家好!");
p.say("Carry", 18);
Class cls = Class.forName("reflect.Person");
Object o = cls.newInstance();
//sayHello(String)
Method m = cls.getMethod("sayHello", String.class);
m.invoke(o, "哈喽~");
Method m1 = cls.getMethod("say", String.class,int.class);
m1.invoke(o, "兔子",22);