反射:
发生在程序运行期间的动态机制|行为
是java的唯一动态机制–>反射机制
Java反射机制,可以实现以下功能:
①在运行时判断任意一个对象所属的类;
②在运行时构造任意一个类的对象;
③在运行时判断任意一个类所具有的成员变量和方法;
④在运行时调用任意一个对象的方法;
⑤生成动态代理;
反射的源头:
Class Class类型的实例可以用来表示java中运行期间的一个类型
Class对象
Class对象在类第一次加载到内存后就已经存在的,唯一的,不变的,每一个类型只有一个
Class对象可以操作这个类的所有内容(属性方法构造器…)
如何获取反射的源头:Class对象
1.类名.class
2.Class.forName(权限定名) 权限定名:包名.类名 -->推荐
3.对象.getClass()
public class Reflect {
public static void main(String[] args) throws ClassNotFoundException {
//1.类名.class
Class<String> cls1 = String.class;
System.out.println(cls1.toString());
//2.Class.forName(权限定名)
Class cls2 = Class.forName("java.lang.String");
System.out.println(cls2);
System.out.println(cls2==cls1);
//3.对象.getClass()
Class cls3 = "abc".getClass();
System.out.println(cls3);
System.out.println(cls3==cls1);
//获取当前Class对象所表示类型的父类的Class对象
Class cls4 = cls1.getSuperclass();
System.out.println(cls4);
System.out.println(cls4==Object.class);
//获取基本数据类型的Class对象
System.out.println(Integer.class);
System.out.println(int.class);
System.out.println(int.class==Integer.class);
System.out.println(Integer.TYPE);
System.out.println(Integer.TYPE==int.class);
}
}
反射操作构造器
构造器 getConstructor(类<?>… parameterTypes) 返回一个 构造器对象,该对象反映此 类对象所表示的类的指定公共构造函数。
构造器<?>[] getConstructors() 返回一个包含 构造器对象的数组, 构造器对象反映了此 类对象所表示的类的所有公共构造函数。
以上都是获取公共的,被public修饰的构造器
构造器 getDeclaredConstructor(类<?>… parameterTypes) 返回一个 构造器对象,该对象反映此 类对象所表示的类或接口的指定构造函数。
构造器<?>[] getDeclaredConstructors() 返回 构造器对象的数组, 构造器对象反映由此 类对象表示的类声明的所有构造函数。
反射创建对象
Class–>T newInstance() 默认调用类型的空构造为对象初始化信息 -->不推荐使用
不能确定一个类型是否存在空构造,极有可能遇到运行时异常
Constructor—> T newInstance(Object… initargs) 创建对象的同时调用当前构造器为对象初始化信息
public class Reflect {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//获取构造器
Class<User> cls = User.class;
Constructor[] cons = cls.getConstructors();
for(Constructor con:cons){
System.out.println(con);
}
Constructor<User> con = cls.getDeclaredConstructor(String.class,int.class);
System.out.println(con);
//创建对象
//1)
User user = User.class.newInstance();
System.out.println(user);
//2) 私有内容需要忽略权限使用
con.setAccessible(true); //忽略权限
User user2 = con.newInstance("laopei",1234);
System.out.println(user2);
}
}
class User{
private String name;
private int pwd;
//公共的
public User() {
}
public User(String name) {
this.name = name;
}
//私有的
private User(String name, int pwd) {
this.name = name;
this.pwd = pwd;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPwd() {
return pwd;
}
public void setPwd(int pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", pwd=" + pwd +
'}';
}
}
反射操作属性
字段 getField(String name) 返回 字段对象,该对象反映此 类对象表示的类或接口的指定公共成员字段。
字段[] getFields() 返回一个包含 字段对象的数组, 字段对象反映此 类对象所表示的类或接口的所有可访问公共字段。
字段 getDeclaredField(String name) 返回 字段对象,该对象反映此 类对象表示的类或接口的指定声明字段。
字段[] getDeclaredFields() 返回 字段对象的数组, 字段对象反映由此 类对象表示的类或接口声明的所有字段。
void set(Object obj, Object value) 将指定对象参数上此 字段对象表示的字段设置为指定的新值。
Object get(Object obj) 返回指定对象上此 字段表示的字段的值。
反射操作方法
方法 getMethod(String name, 类<?>… parameterTypes) 返回 方法对象,该对象反映此 类对象表示的类或接口的指定公共成员方法。
方法[] getMethods() 返回一个包含 方法对象的数组, 方法对象反映此 类对象所表示的类或接口的所有公共方法,包括由类或接口声明的那些以及从超类和超接口继承的那些。
方法 getDeclaredMethod(String name, 类<?>… parameterTypes) 返回 方法对象,该对象反映此 类对象表示的类或接口的指定声明方法。
方法[] getDeclaredMethods() 返回一个包含 方法对象的数组, 方法对象反映此 类对象表示的类或接口的所有已声明方法,包括public,protected,default(package)访问和私有方法,但不包括继承的方法。
Object invoke(Object obj, Object… args) 在具有指定参数的指定对象上调用此 方法对象表示的基础方法。
public class Reflect {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
User user = new User("zhangsan");
//User类的Class对象
Class<User> cls = User.class;
testMethod(cls,user);
}
//测试方法
public static void testMethod(Class<User> cls,User user) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method[] methods = cls.getMethods();
for(Method m:methods){
System.out.println(m);
}
//私有方法
Method method = cls.getDeclaredMethod("haha",int.class);
//调用方法
method.setAccessible(true);
System.out.println(method.invoke(user,100));;
System.out.println(method.invoke(null,100));;
Method m = cls.getMethod("getName");
System.out.println(m.invoke(user));
}
//测试属性
public static void testField(Class<User> cls,User user) throws NoSuchFieldException, IllegalAccessException {
Field field = cls.getDeclaredField("name");
System.out.println(field.getName());
System.out.println(field.getType());
//忽略权限
field.setAccessible(true);
field.set(user,"zhangsanfeng");
System.out.println(field.get(user));
}
}
反射操作数组
static Object newInstance(类<?> componentType, int length) 创建具有指定组件类型和长度的新数组。
static Object get(Object array, int index) 返回指定数组对象中索引组件的值。
static void set(Object array, int index, Object value) 将指定数组对象的索引组件的值设置为指定的新值。
public class Class005_Reflect {
public static void main(String[] args) throws Exception {
testArray();
test(String.class);
}
public static void test(Class<String> cls){
//int getModifiers() 返回此类或接口的Java语言修饰符,以整数编码。
System.out.println(cls.getModifiers());
System.out.println(Modifier.toString(cls.getModifiers()));
//类<?>[] getInterfaces() 返回由此对象表示的类或接口直接实现的接口。
System.out.println(Arrays.toString(cls.getInterfaces()));
//String getName() 返回此 类对象表示的实体名称(类,接口,数组类,基本类型或void),作为 String 。
System.out.println(cls.getName());
//String getSimpleName() 返回源代码中给出的基础类的简单名称。
System.out.println(cls.getSimpleName());
}
//简单操作数组
public static void testArray(){
int[] arr = (int[]) Array.newInstance(int.class,5);
Array.set(arr,2,200);
System.out.println(Arrays.toString(arr));
System.out.println(Array.get(arr,2));
}
}