类需要经过 加载, 连接, 初始化三个步骤来进行初始化. 加载是把class文件读入内存创建一个class对象, 连接分为三步,第一步是验证是否是正确的结构, 第二步是准备, 为类的静态成员分配内存,初始化默认值, 第三步是解析, 将类的二进制数据中的符号替换为直接引用.初始化是静态代码块,构造代码块等的执行等.
类加载器有三种, Bootstrap引导类加载器, 负责java核心类的加载,如 System String等(在rt.jar文件中). Extention扩展类加载器, 负责jre扩展目录中的jar包的加载, 在jre的lib目录下的ext目录. System系统类(也叫应用类)加载器,负责来自java命令的class文件及环境变量中的jar包和类路径
类的反射在字节码文件阶段(X.class文件)的获取方式为 class.forName("类名"), 在加载到jvm之后字节码阶段(X.class)获取的方式为 X.class, 在创建对象之后获取的方式为 x.getClass()
反射得到的类获取一个新实例为 clazz.newInstance() 不可以传入参数, 有参构造可以通过Constructor c = clazz.getConstructor(String.class, int.class) 获取构造函数,然后用c.newInstance("xxx", 1)来创建对象. 通过Field f = clazz.getField()获取单个成员变量,通过getFields()获取所有成员变量,私有的属性可以通过调用getDeclaedField()获取私有属性,然后用f.setAccessible(true)去除私有权限,就可以用f.set(对象, 修改值) 来修改某个对象的f属性的值
获取方法可以用 clazz.getMethod("xxx", int.class) 基本和获取属性差不多,后面是需要传参的参数的类型, 可以用Method.invoke(对象, 参数) 调用对象的method方法.
枚举是把所有有限的变量都列出来, 如一年有12个月, 一周有七天等, 单例类是只有一个实例, 多例类就是有有限个数的多个实例,如枚举类.
最简单的枚举类: (枚举项必须放在枚举类的第一行, 枚举类的构造函数必须而且是默认私有的, 枚举类可以在switch里面使用)
public enum Week { MON, TUE, WED; }
使用构造方法的方式: (可以用getName获取名字,可以给枚举类的实例加一些字段,方法等,对枚举类进行扩展)
public enum Week { MON("周一"), TUE("周二"), WED("周三"); private String name; private Week(String name) { this.name = name; } public String getName() { return name; } }