当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过 **加载,连接,初始化 **三步来实现对这个类进行初始化。
加载:就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象。
连接:验证,是否有正确的内部结构,并和其他类协调一致。准备,负责为类的静态成员分配内存,并设置默认初始化值。解析,将类的二进制数据中的符号引用替换为直接引用。
初始化
创建类的实例
类的静态变量,或者为静态变量赋值
类的静态方法
使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
初始化某个类的子类
直接使用java.exe命令来运行某个主类
反射是在运行时,而非编译时,动态获取类型的信息,比如接口信息,成员信息,方法信息,构造方法信息,再根据这些动态获取到的信息来创建对象,访问、修改成员,使用方法。 ------- 《JAVA编程的逻辑》
Class没有公共的构造方法。注意Class类不是class,大小写要区分。这里的前两种获取Class类对象的方法需要明确Person类型。而第三种需要指定这种类型的字符串就行。
//通过Object类中的getClass()方法 , 返回Object类的运行时类
Person p = new Person();
Class c = p.getClass();
//通过 类名.class 获取到字节码文件对象
Class c2 = Person.class;
//将类名作为字符串传递给Class类中的静态方法forName
Class c3 = Class.forName("Person");
1、Class是个泛型类,有一个类型参数,getClass()并不知道具体的类型,只能返回 Class>。
2、接口也有Class对象。
3、**基本类型 **没有getClass()方法,但都有对应的Class对象。void 作为特殊的返回类型,也有Class对象。
//基本类型。这里就不列举完了,还有Double,Character等
Class<Integer> inCls = int.class;
Class<Byte> byteCls = byte.class;
。。。。
//void类型
Class<void> voidCls = void.class;
4、对于数组,每种类型的数组都有对应的Class对象,每个 **维度 **都有一个。
在反射机制中,把类中的成员(构造方法、成员方法、成员变量)都封装成了对应的类进行表示。
其中,构造方法使用类 Constructor 表示。
//获取public修饰, 指定参数类型所对应的构造方法
public Constructor<T> getConstructor(Class<?>... parameterTypes)
//获取指定参数类型所对应的构造方法(包含私有的)
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
//获取所有的public 修饰的构造方法
public Constructor<?>[] getConstructors()
//获取所有的构造方法(包含私有的)
public Constructor<?>[] getDeclaredConstructors()
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException {
//获取Class对象
Class c = Class.forName("cn.itcast_01_Reflect.Person");//包名.类名
//获取所有的构造方法
//这里不止有一个构造方法,所以运用集合来存储
Constructor[] cons = c.getDeclaredConstructors();
//用循环来打印方法
for (Constructor con : cons) {
System.out.println(con);
}
System.out.println("------------------------");
//获取一个构造方法,这里getConstructor的参数就是指定构造方法的参数。
//public Person()
Constructor con1 = c.getConstructor(null);
System.out.println(con1);
//public Person(String name)
Constructor con2 = c.getConstructor(String.class);
System.out.println(con2);
//private Person(String name, int age)
Constructor con3 = c.getDeclaredConstructor(String.class, int.class);
System.out.println(con3);
//public Person(String name, int age, String address)
Constructor con4 = c.getDeclaredConstructor(String.class, int.class, String.class);
System.out.println(con4);
}
}
获取 **构造方法 **,步骤如下:
获取 私有构造方法 ,步骤如下:
AccessibleObject 类是 Field、Method 和 Constructor 对象的 父类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力,也就是可以打破JAVA的访问权限。
//参数值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。参数值为 false 则指示反射的对象应该实施 Java 语言访问检查。
public void setAccessible(boolean flag) throws SecurityException
在反射机制中,把类中的成员变量使用类 Field 表示。
//获取指定的 public修饰的变量
public Field getField(String name)
//获取指定的任意变量
public Field getDeclaredField(String name)
//获取所有public 修饰的变量
public Field[] getFields()
//获取所有的 变量 (包含私有)
public Field[] getDeclaredFields()
public class FieldDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException {
//获取Class对象
Class c = Class.forName("cn.itcast_01_Reflect.Person");
//获取成员变量
//多个变量,运用数组来存储
Field[] fields = c.getDeclaredFields();
//遍历数组,访问数组
for (Field field : fields) {
System.out.println(field);
}
System.out.println("-----------------");
//一个变量
//public int age;
Field ageField = c.getField("age");
System.out.println(ageField);
//private String address,这里是私有变量,也能被获取。
Field addressField = c.getDeclaredField("address");
System.out.println(addressField);
}
}
获取成员变量,步骤如下:
获取Class对象
获取构造方法
通过构造方法,创建对象
获取指定的成员变量(私有成员变量,通过setAccessible(boolean flag)方法暴力访问)
//在指定对象obj中,将此 Field 对象表示的成员变量设置为指定的新值
public void set(Object obj, Object value)
//返回指定对象obj中,获取对象的值
public Object get(Object obj)
//1,获取Class对象
Class c = Class.forName("cn.itcast_01_Reflect.Person");
//2,获取构造方法
//public Person(String name, int age, String address)
//这里要传入对应构造方法的参数类型的class对象!!!!!!!!!
Constructor con = c.getConstructor(String.class, int.class, String.class);
//3,通过构造方法,创建对象
Object obj = con.newInstance("小明", 23, "哈尔滨");
//4,获取指定的方法
//public void method1() 没有返回值没有参数的方法
//Method m1 = c.getMethod("method1", null);
//public String method4(String name)
Method m4 = c.getMethod("method4", String.class);
//5,执行找到的方法
//m1.invoke(obj, null);
Object result = m4.invoke(obj, "itcast");
在反射机制中,把类中的成员方法使用类 Method 表示。
//获取 public 修饰的方法
public Method getMethod(String name, Class<?>... parameterTypes)
//获取任意的方法,包含私有的
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
//参数1: name 要查找的方法名称; 参数2: parameterTypes 该方法的参数类型
//这里因为返回不只一个方法,因此运用Method的数组来存放。类似前面的。
//获取本类与父类中所有public 修饰的方法
public Method[] getMethods()
//获取本类中所有的方法(包含私有的)
public Method[] getDeclaredMethods()
//执行指定对象obj中,当前Method对象所代表的方法,方法要传入的参数通过args指定
public Object invoke(Object obj, Object... args)
获取私有成员方法,步骤如下:
也就是运用 setAccessible(true); 开启暴力访问。
1、获取.Class文件对象的方法三种。
2、获取构造方法。
3、获取成员变量。
4、获取成员方法。
5、暴力破除JAVA语言局限,setAccessible (true)。