Java’s One…
0x01
何为反射
正向
- 导入类包(import)
- 实例化对象(new)
- 调用属性(object.field_name)
- 调用方法(object.method_name)
反向 与正向相对应调用
- java.lang.Class
- java.lang.reflect.Constructor
- java.lang.reflect.Field
- java.lang.reflect.Method
反射不需要有明确的类型对象,使用Object表示即可。
java.lang.Class
内部可以记录类的成员、接口等信息,其为一个表示类的类。
类定义:
public final class Class<T>
extends Object
implements Serializable, GenericDeclaration, Type, AnnotatedElement
获取Class类。
public final Class<?> getClass()
- 使用
类名.class
1. public static Class<?> forName(String className) throws ClassNotFoundExceptio
第二种多用于程序开发,第三种多用框架设计,为反射机制使用的方法。
forName后续
- 实例化对象
public T newInstance() throws InstantiationException,IllegalAccessException
这是一个Class类的一个无参构造方法,也就会调用所表示类的无参构造方法,返回一个Class所表示的类的实例。
- 获取类中构造方法
-
public Constructor<?>[] getConstructors()throws SecurityException
-
public Constructor<T> getConstructor(Class<?>... parameterTypes)throws NoSuchMethodException,SecurityException
返回java.lang.reflect.Constructor类
Demo:
public static void main(String[] args) throws ClassNotFoundException {
Class<?> cls = Class.forName("java.lang.String");
Constructor<?>[] cons = cls.getConstructors();
for (int i = 0; i < cons.length; i++) {
System.out.println(cons[i]);
}
}
Show:
public java.lang.String(byte[],int,int)
public java.lang.String(byte[],java.nio.charset.Charset)
public java.lang.String(byte[],java.lang.String) throws java.io.UnsupportedEncodingException
public java.lang.String(byte[],int,int,java.nio.charset.Charset)
public java.lang.String(byte[],int,int,java.lang.String) throws java.io.UnsupportedEncodingException
public java.lang.String(java.lang.StringBuilder)
public java.lang.String(java.lang.StringBuffer)
public java.lang.String(byte[])
public java.lang.String(int[],int,int)
public java.lang.String()
public java.lang.String(char[])
public java.lang.String(java.lang.String)
public java.lang.String(char[],int,int)
public java.lang.String(byte[],int)
public java.lang.String(byte[],int,int,int)
关于Class有参构造函数
函数定义:
public T newInstance(Object... initargs)throws InstantiationException,IllegalAccessException,IllegalArgumentException,InvocationTargetException
有参构造函数调用Demo:
class Student {
private String name;
private Integer age;
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "name:" + this.name + ";age:" + this.age;
}
}
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("com.test.Student");
Constructor<?> con = cls.getConstructor(String.class, Integer.class);
Object stu = con.newInstance("idlefire", 21);
System.out.println(stu);
}
}
Show:
name:idlefire;age:21
Class类调用无参构造,Constructor类调用有参构造方法
- 获取类中方法
获取父类以及本类全部方法
public Method[] getMethods()throws SecurityException
获取父类指定方法
public Method getMethod(String name,Class<?>... parameterTypes)throws NoSuchMethodException,SecurityException
获取本类全部方法
public Method[] getDeclaredMethods()throws SecurityException
获取本类指定方法
public Method getDeclaredMethod(String name,Class<?>... parameterTypes)throwsNoSuchMethodException,SecurityException
String name 指定是方法名
- 反射中的invoke方法
方法定义:
public Object invoke(Object obj,Object... args)throws IllegalAccessException,IllegalArgumentException,InvocationTargetException
利用上面获取的Method对象,当该对象调用invoke方法时,相当与从指定对象中调用该Method所代表的方法。
Demo:
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("com.test.Student4");
Object obj = cls.newInstance();
Method setnameMethod = cls.getMethod("setName", String.class);
Method getnameMethod = cls.getMethod("getName");
setnameMethod.invoke(obj, "idlefire");
System.out.println(getnameMethod.invoke(obj));
}
class Student4 {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Show:
- 利用反射调用类中属性
包含继承类 获取全部属性
public Field[] getFields() throws SecurityException
获取指定属性
public Field getField(String name)throwsNoSuchFieldException,SecurityException
仅限于本类 获取全部属性
public Field[] getDeclaredFields()throws SecurityException
获取指定属性
public Field getDeclaredField(String name)throws NoSuchFieldException,SecurityException
设置和获取属性
public void set(Object obj,
Object value)
throws IllegalArgumentException,
IllegalAccessException
...
public Object get(Object obj)
throws IllegalArgumentException,
IllegalAccessException
Demo:
class Student5 {
private String name;
}
...
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("com.test.Student5");
Object obj = cls.newInstance();
Field namefield = cls.getDeclaredField("name");
namefield.setAccessible(true);
namefield.set(obj, "idlefire");
System.out.println(namefield.get(obj));
}
}
其中setAccessible方法是为了能够访问非公开的属性,在Construction,Method,Field三个类中有一个共同的父类AccessibleObject,定义了取消封装的操作:setAccessible(Boolean flag)。
未使用setAccessible:
(ง •_•)ง