文章目录
JavaSE-16 【反射】
第一章 反射介绍
1 反射的概念
反射(Reflection)机制是Java语言特性之一,是Java被视为动态(或准动态)语言的一个关键特性。
- JAVA机制反射是在运行状态中:
- 对于任意一个类,都能够知道这个类的所有属性和方法;
- 对于任意一个对象,都能够调用它的任意一个方法和属性;
- 这种动态获取的信息以及动态调用对象的方法的功能,称为java语言的反射机制。
2 反射的特征
- 运行时创建实例:在程序运行期间能够创建对象
- 运行时调用方法:在程序运行期间能够调用方法
- 运行时更改属性:在程序运行期间能够设置属性
3 反射的功能
通过Java反射可以实现以下功能:
- 在运行时探知任意一个实例所属的类。
- 在运行时构造任意一个类的实例。
- 在运行时探知任意一个类所具有的方法和属性。
- 在运行时调用任意一个实例的方法。
第二章 反射的基本操作
2.1 反射操作–常用方法
1、获取类的Class对象
方式一:调用运行时类的属性:.class
方式二:通过运行时类的对象,调用getClass()
方式三:调用Class的静态方法:forName(String classPath)
2、获取类的路径和名称
--.getPackage().getName(); 获取包的名称
--.getSimpleName(); 获取类的名称
--.getName(); 获取类的全路径
3、获取类的属性
--.getFields(); 获取所有公开属性
--.getDeclaredFields(); 获取所有属性包括私有属性
--.getField(String name); 根据指定属性名获取公开的属性
--.getDeclaredField(String name);根据指定属性名获取属性包括私有属性
4、获取类的构造方法
--.getConstructor();获取公开的无参构造
--.getConstructor(Class<?>... parameterTypes);获取指定参数类型的公开的有参构造
--.getConstructors();获取所有公开的构造方法
--.getDeclaredConstructors();获取所有的构造方法,包括私有的
--.getDeclaredConstructor(Class<?>... parameterTypes);根据指定参数的类型获取指定的构造方法包括私有的
5、反射创建对象
无参构造对象
--字节码对象.newInstance();反射无参构造创建对象
有参构造对象
--字节码对象.getDeclaredConstructor(Class<?>... parameterTypes); 获取构造器对象
--构造器对象.setAccessible(true); 设置私有状态的权限为true
-- 构造器对象.newInstance(Object ... initargs); 构造创建对象
6、操作成员变量并赋值
--.getDeclaredField("username");根据指定名获取变量名
--属性名.setAccessible(true);设置其访问权限为true
--属性名.ser(Object obj,Object value);给指定的对象的属性赋值
--属性名.get(Object obj);获取指定对象的属性的属性值
7、反射调用成员方法
--getDeclaredMethods();获取所有的方法,包括私有的
--.getDeclaredMethod(String name, Class<?>... parameterTypes);根据指定方法名和参数类型获取指定的有参数的方法
--方法名.invoke(Object obj, Object... args);指定执行此方法的对象和参数
2.2 反射操作–类的字节码对象
方式一:调用运行时类的属性:.class
方式二:通过运行时类的对象,调用getClass()
方式三:调用Class的静态方法:forName(String classPath)
- 编写模板类
package com.hx;
/*
模板类
*/
public class User {
//成员属性
private String username;
public String pwd;//公开的属性
private int age;
private String address;
//成员方法
public void work(){
System.out.println("用户在工作!");
}
public String speak(String language){
System.out.println("用户的母语是"+language);
return language;
}
//公开的无参构造
public User() {
System.out.println("我是无参构造");
}
//公开的有参构造
public User(String username, int age) {
this.username = username;
this.age = age;
}
//私有的的有参构造
private User(String username, int age, String address) {
this.username = username;
this.age = age;
this.address = address;
}
//私有属性的set和get方法
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
- 测试
/*
反射操作类的字节码对象:三种方式
*/
//1、通过类名.class
Class<User> uClass = User.class;
System.out.println(uClass);
//2、通过运行时类的实例对象,调用getClass()
User u1 = new User();
Class<? extends User> aClass = u1.getClass();
//3、调用Class的静态方法:forName(String classPath)
Class<?> bClass = Class.forName("com.hx.User");
2.3 反射操作–类的路径和名称
/*
反射操作类的路径和名称
*/
//4、获取当前类所在的包的包名称
Package aPackage = aClass.getPackage();
String name = aPackage.getName();
System.out.println("当前类所在的包的包名称:" + name);
//5、获取类的名称
String simpleName = aClass.getSimpleName();
System.out.println(simpleName);
//6、获取完整的类的名称
String name1 = aClass.getName();
System.out.println(name1);
2.4 反射操作–类的属性
/*
反射操作属性
*/
//7、获取公开的成员变量
Field[] fields = aClass.getFields();
System.out.println(Arrays.toString(fields));
System.out.println("-----------------------------------");
//8、获取包括私有在内的属性
Field[] declaredFields = aClass.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field);
}
System.out.println("-----------------------------------");
//9、获取公开指定的变量名
Field pwd = aClass.getField("pwd");
System.out.println(pwd);
System.out.println("-----------------------------------");
//10、获取指定私有属性的变量的名称
Field age = aClass.getDeclaredField("age");
System.out.println(age);
2.5 反射操作–构造方法
/*
反射操作构造方法
*/
//11、获取公开的无参构造
Constructor<? extends User> c1 = aClass.getConstructor();
System.out.println(c1);
System.out.println("=======================================");
//12、获取指定参数类型的公开的有参构造
Constructor<? extends User> c2 = aClass.getConstructor(String.class, int.class);
System.out.println(c2);
System.out.println("=======================================");
//13、获取所有公开的构造方法
Constructor<?>[] constructors = aClass.getConstructors();
for (Constructor<?> c : constructors) {
System.out.println(c);
}
System.out.println("=======================================");
//14、获取所有的构造方法,包括私有的
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
for (Constructor<?> d : declaredConstructors) {
System.out.println(d);
}
System.out.println("=======================================");
//15、根据指定参数的类型获取指定的私有的构造方法
Constructor<? extends User> d2 = aClass.getDeclaredConstructor(String.class, int.class, String.class);
System.out.println(d2);
System.out.println("=======================================");
2.7 反射操作–创建对象
/*
通过反射创建对象
*/
//16、反射无参构造创建对象
User u3 = aClass.newInstance();
u3.setUsername("tom");
u3.setAge(19);
u3.setAddress("北京");
System.out.println(u3);
System.out.println("=======================================");
//17、反射有参构造创建对象
/*
注意事项:
1、使用有参的构造创建对象,那么模板类中构造方法可以是公开的,也可以是私有的
2、不能使用字节码对象直接调用newInstance(),执行有参构造的操作
3、需要使用字节码对象先获取构造器对象,如果是私有构造方法,需要设置访问权限为true
4、再通过构造器对象调用newInstance(参数...)来创建对象
*/
//获取指定参数类型的构造器
Constructor<? extends User> constructor =
aClass.getDeclaredConstructor(String.class, int.class, String.class);
//设置此构造器的权限为可以被访问
constructor.setAccessible(true);
//构造创建对象
User u4 = constructor.newInstance("lucy", 22, "美国");
System.out.println(u4);
System.out.println("=======================================");
2.7 反射操作–成员变量并赋值
/*
操作成员变量并赋值
*/
//18、根据指定名获取变量名
//私有属性的名称
Field username = aClass.getDeclaredField("username");
//设置其访问权限为true
username.setAccessible(true);
//给指定的对象的属性赋值
username.set(u4,"Anny");
System.out.println(u4);
//获取指定对象的属性的属性值
Object o = username.get(u4);
System.out.println(o);
System.out.println("=======================================");
2.8 反射操作–成员方法
/*
反射调用成员方法
*/
//19、获取所有的方法,包括私有的
Method[] methods = aClass.getDeclaredMethods();
//遍历数组---自定义的成员方法、setter/getter、toString
for (Method method : methods) {
System.out.println(method);
}
System.out.println("=======================================");
//20、根据指定方法名获取指定的无参数的方法
Method work = aClass.getDeclaredMethod("work");
//调用方法:指定对象和参数
work.invoke(u4);
//21、根据指定方法名和参数类型获取指定的有参数的方法
Method speak = aClass.getDeclaredMethod("speak", String.class);
//调用方法:指定对象和参数
Object language = speak.invoke(u4, "法语");
System.out.println(language);
}