java中每个类在编译后都会生成对应的class文件,Java中的所有类,必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的。
1.装载:类加载器将编译好的class装载到内存
2.链接:验证:确保被加载类的正确性; 准备:为类的静态变量分配内存,并将其初始化为默认值;解析:把类中的符号引用转换为直接引用;
3.初始化:为类的静态变量赋予正确的初始值;
(说明:装载不是加载,一个应用程序总是由n多个类组成,Java程序启动时,并不是一次把所有的类全部加载后再 运行,它总是先把保证程序运行的基础类一次性加载到jvm中,其它类等到jvm用到的时候再加载,这样的好处是节省了内存的开销,是java动态性的一种体现 )
java的类加载器
Bootstrap Loader - 负责加载系统类 负责Java核心类的加载
ExtClassLoader - 负责加载扩展类 负责JRE的扩展目录中jar包的加载
AppClassLoader - 负责加载应用类 加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。
在这里java采用了委托模型机制,这个机制简单来讲,就是“类装载器有载入类的需求时,会先请示其Parent使用其搜索路径帮忙载入,如果Parent 找不到,那么才由自己依照自己的搜索路径搜索类”。可见性机制:可见性的原理是子类的加载器可以看见所有的父类加载器加载的类,而父类加载器看不到子类加载器加载的类。单一性机制:根据这个机制,父加载器加载过的类不能被子加载器加载第二次。虽然重写违反委托和单一性机制的类加载器是可能的,但这样做并不可取。
类加载器将class文件加载到方法区中,在堆内存创建唯一的字节码对象也就是class对象。
类的初始化时间
- 创建类的实例
- 类的静态变量,或者为静态变量赋值
- 类的静态方法
- 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个主类
获取class对象三种方式:
方式一: 通过Object类中的getObject()方法
Person p = new Person();
Class c = p.getClass();
方式二: 通过 类名.class 获取到字节码文件对象(任意数据类型都具备一个class静态属性,看上去要比第一种方式简单)。
Class c2 = Person.class;
方式三: 通过Class类中的方法(将类名作为字符串传递给Class类中的静态方法forName即可)。
Class c3 = Class.forName("com.xxx.xxx.xxxPerson");(正确的包名位置)
通过反射获取构造方法并使用
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException {
//获取Class对象
Class c = Class.forName("cn.itcast_01_Reflect.Person");//包名.类名
//getConstructors只返回制定参数类型访问权限是public的构造器。
//Constructor[] cons = c.getConstructors();
//getDeclaredConstructors() 这个方法会返回制定参数类型的所有构造器,包括public和非public,当然也包括private。
Constructor[] cons = c.getDeclaredConstructors();
for (Constructor con : cons) {
System.out.println(con);
}
System.out.println("------------------------");
//获取一个构造方法
//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);
}
通过反射方式,获取构造方法,创建对象
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//1,获取到Class对象
Class c = Class.forName("cn.itcast_01_Reflect.Person");//包名.类名
//2,获取指定的构造方法
//public Person()
//Constructor con = c.getConstructor(null);
//public Person(String name, int age, String address)
Constructor con = c.getConstructor(String.class, int.class, String.class);
//3,通过构造方法类中Constructor的方法,创建对象
//Object obj = con.newInstance(null);
Object obj = con.newInstance("小明", 22, "哈尔滨");
//显示
System.out.println(obj);
}
通过反射方式,获取私有构造方法,创建对象
AccessibleObject 类是 Field、Method 和 Constructor 对象的父类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//1,获取到Class对象
Class c = Class.forName("cn.itcast_01_Reflect.Person");//包名.类名
//2,获取指定的构造方法
//private Person(String name, int age)
Constructor con = c.getDeclaredConstructor(String.class, int.class);
//3,暴力反射
con.setAccessible(true);//取消 Java 语言访问检查
//4,通过构造方法类中的功能,创建对象
Object obj = con.newInstance("小明", 23);
System.out.println(obj);
}
通过反射获取成员变量并使用
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException {
//获取Class对象
Class c = Class.forName("cn.itcast_01_Reflect.Person");
//获取成员变量
//多个变量
//Field[] fields = c.getFields();
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);
}
通过反射,创建对象,获取指定的成员变量,进行赋值与获取值操作
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
//1,获取Class对象
Class c = Class.forName("cn.itcast_01_Reflect.Person");
//2,获取构造方法
//public Person(String name)
Constructor con = c.getConstructor(String.class);
//3,通过构造方法,创建对象
Object obj = con.newInstance("小明");
//4,获取指定的成员变量
//public String name;
Field nameField = c.getField("name");
//public int age;
Field ageField = c.getField("age");
//private String address;
Field addressField = c.getDeclaredField("address");
addressField.setAccessible(true); //取消 Java 语言访问检查
//5,通过方法,给指定对象的指定成员变量赋值或者获取值
System.out.println("name = "+ nameField.get(obj));
System.out.println("age = "+ ageField.get(obj));
System.out.println("address = "+ addressField.get(obj));
//赋值
ageField.set(obj, 23);
addressField.set(obj, "凯利广场");
System.out.println("------------------------");
System.out.println("name = "+ nameField.get(obj));
System.out.println("age = "+ ageField.get(obj));
System.out.println("address = "+ addressField.get(obj));
}
通过反射获取成员方法并使用
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException {
//获取Class对象
Class c = Class.forName("cn.itcast_01_Reflect.Person");
//获取多个方法
//Method[] methods = c.getMethods();
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("-----------------------");
//获取一个方法:
//public void method1()
Method method = c.getMethod("method1", null);
System.out.println(method);
//public String method4(String name){
method = c.getMethod("method4", String.class);
System.out.println(method);
//私有方法
//private void method5()
method = c.getDeclaredMethod("method5", null);
System.out.println(method);
}
通过反射,创建对象,调用指定的方法
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//1, 获取Class对象
Class c = Class.forName("cn.itcast_01_Reflect.Person");
//2,获取构造方法
//public Person(String name, int age, String address){
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");
System.out.println("result = " + result);
}
通过反射,创建对象,调用指定的private 方法
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//1, 获取Class对象
Class c = Class.forName("cn.itcast_01_Reflect.Person");
//2,获取构造方法
//public Person(String name, int age, String address){
Constructor con = c.getConstructor(String.class, int.class, String.class);
//3,通过构造方法,创建对象
Object obj = con.newInstance("小明", 23, "哈尔滨");
//4,获取指定的方法
//private void method5(){
Method m5 = c.getDeclaredMethod("method5", null);
//5,开启暴力访问
m5.setAccessible(true);
//6,执行找到的方法
m5.invoke(obj, null);
}
反射中的泛型擦除
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
ArrayList<Integer> list = new ArrayList<Integer>();
//添加元素到集合
list.add(new Integer(30));
list.add(new Integer("12345"));
list.add(123);
//list.add("哈哈");//因为有泛型类型的约束
System.out.println(list);
//通过反射技术,实现添加任意类型的元素
//1, 获取字节码文件对象
//Class c = list.getClass();
//Class c = ArrayList.class;
Class c = Class.forName("java.util.ArrayList");
//2, 找到add()方法
// public boolean add(E e)
Method addMethod = c.getMethod("add", Object.class);
//3, 执行add()方法
addMethod.invoke(list, "哈哈");// list.add("哈哈");
System.out.println(list);
}