框架:
1. 类变量 和 类方法 ( static)
类变量(静态变量) 和 类方法 可以被 类 直接访问!
类变量 被 所有 类的对象共享! 任何一个该类的对象去 获取该类的类变量时,得到的都是相同的值!
类变量存放在哪:
在类加载时,会在堆空间中生成一个class 对象(原型对象),类变量就存放在这里!
语法:
访问修饰符 static 数据类型 类变量名称;
使用方法:
类名.静态变量 或者 对象名.静态变量 (遵守访问权限)
类方法和普通方法都是随着类加载而加载的,类方法中没有this 参数, 普通方法中有this参数
类方法中不能使用this和super
类方法中只能访问 静态变量和静态方法
非静态方法 可以访问 静态成员和非静态成员
代码块:(初始化块)
是 类 的一部分,就是只有方法体的方法
语法:
[修饰符] { //修饰符只能写static,也可以不写
代码;
}
代码块相当于 另一种形式的 构造器, 是对构造器的补充,可以做初始化操作
如果多个构造器中都有重复的语句,可以提取到 代码块中,降低代码的冗余。 无论使用哪个构造器创建对象,都会先调用代码块。
细节:
1. static 静态代码块,会随着 类的加载 而执行, 并且只会执行一次
普通代码块,每创建一个对象,就会执行一次
2. 类什么时候被加载:
2.1 创建对象时(new)
2.2 创建子类对象时,父类也会被加载, 先加载父类,再加载子类
2.3 使用类的静态成员时!
3. 普通代码块只有在创建对象的时候调用。
4. 当创建一个对象时,一个类中 调用顺序是:
4.1 先调用静态代码块和静态属性初始化; 静态代码块 和静态属性初始化 如果都存在, 就看谁在前,谁先调用
4.2 普通代码块和普通属性初始化; 普通代码块 和 普通属性初始化 如果都存在,就看谁在前,谁先调用
4.3 调用构造器!
5. 构造器 里 隐藏了 super() 和 调用本类的普通代码块
6. 当存在继承关系时, 代码块和构造器的调用顺序:
6.1: 父类的静态代码块 和 静态属性初始化(按定义的先后顺序)
6.2: 子类的静态代码块 和 静态属性初始化(按定义的先后顺序)
6.3: 父类的普通代码块 和 普通属性初始化
6.4: 父类的构造器
6.5: 子类的普通代码块 和 普通属性初始化
6.6: 子类的构造器
单例模式:
保证 从 程序运行 到 程序结束之间, 一个类只能存在一个对象!并且该类只提供一个构造对象的方法
两种方式: 饿汉式 和 懒汉式
饿汉式: 你有可能不需要使用对象,但也给你创建好了。(类加载时,就创建好了)
1. 构造器私有化 ==》 防止用户直接new对象
2. 类的内部创建对象( private static 类名 对象名 = new 类名();
3. 提供一个公共的static 方法返回 对象 ( public static 类名 getInstance(){ return 对象名;} )
4. 通过 类名.getInstance().var 即可获得对象
懒汉式:
1. 构造器私有化
2. 定义一个static 静态属性对象: private static 类名 对象名; //注意! 这里不要new! 否则就变成饿汉式了
3. 提供一个public 的static 方法,返回一个对象: public static 类名 getInstance(){ if(对象名 == null) { 对象名 = new 类名(); } return 对象名;}
饿汉式 vs 懒汉式:
1. 创建对象的时机不同。 饿汉式 是在类加载时就创建了对象; 懒汉式 是在使用时才创建对象;
2. 饿汉式不存在线程安全的问题, 懒汉式存在线程安全的问题 ( if(对象名 == null) 这个判断就存在线程安全问题)
3. 饿汉式存在资源浪费的可能, 因为如果创建的对象没有使用,那么就浪费了。(比如当 类名.静态变量 时就不使用对象); 懒汉式是在使用时才创建对象,所以不会浪费。
java.lang.Runtime 就是典型的饿汉式
final 关键字:
final 可以修饰 类, 属性, 方法, 局部变量
(1) 当不希望该类被继承是, 加final
(2)当属性不希望被修改时,加final
(3)当方法不希望被重写时,加final
(4)当局部变量不希望被修改时,加final
细节:
1. final 修饰的属性,又被称为 常量, 命名规范: XXX_XXX
2. final修饰的属性,在定义时必须初始化,并且之后不能再修改
可以在定义时直接初始化,也可以先声明,然后在构造器或者代码块中赋值!
3. 如果final 修饰的是static 属性, 则只能在定义时直接赋值,或者在静态代码块中赋值,不能在构造器中赋值!
4. final 类 不能被继承, 但是可以创建对象
5. 如果类 不是 final 类, 但是类中 有 final方法, 该方法可以被子类使用,但不能被重写,但是该类可以被继承!
6. 一般来说,如果一个类是final 类, 那么就没有必要再声明final方法了
7. final 和 static 通常搭配使用,效率更高,因为一起使用时不会进行类加载。 底层编译器做了优化处理。
8. 包装类(Integer, Boolean, Float,Double等),和String类都是final 类,都不能被继承
9. 形参里也可以加final, 但是在方法体中不能修改final常量的值
抽象类:
当父类的某个方法不确定时,就用abstract 修饰, 有抽象方法的类,就是抽象类。
一般情况,抽象类会被继承, 并由其子类重写抽象方法
细节:
1. 抽象方法 不能有 方法体
2. 抽象类不能实例化!
3. 抽象类 不一定 要包含 抽象方法, 抽象类可以没有抽象方法!
一旦 一个类中包含了抽象方法, 那么该类必须是抽象方法!
4. abstract 只能修饰 类 和 方法, 不能修饰 属性和其它的
5. 抽象类 还是 类, 它可以包括 非抽象方法,构造器,代码块, 静态属性等等
6. 如果一个类 继承了抽象类, 则必须实现抽象类的所有抽象方法,除非它自己也声明为抽象类!
7. 抽象方法不能是用 private,final,static 来修饰, 因为这三个关键字都和重写相违背
模版设计模式:
1. 设计一个抽象 模版类(Template),里面包含 相同方法 和 不同方法
2. 编写相同方法
3. 将不同的方法 写成 抽象方法,让子类继承后改写
4. 子类继承模版类,重写 模版中的抽象方法