框架:

Day 13 面向对象高级_代码块

 

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. 子类继承模版类,重写 模版中的抽象方法