1、昨日复习

  1. 如何实现向下转型?需要注意什么问题?如何解决此问题?

  2. == 和 equals()有何区别?

  3. class User{
    String name;
    int age;
    //重写其equals()方法
    }
    4. 写出8种基本数据类型及其对应的包装类

  4. 基本数据类型、包装类与String三者之间如何转换

    2、关键字:static

    我们有时候希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份,例如所有的中国人都有个国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中都单独分配一个用于代表国家名称的变量。
    1、static:静态的
    2、static可以用来修饰:属性、方法、代码块、内部类
    3、使用static修饰属性:静态变量 类变量
    3.1属性:按是否使用static修饰,又分为:静态属性 vs 非静态属性(实例变量)
    实例变量:我们创建了类的多个对象,每个对象都独立的拥有一类中的非静态属性。当修改其中一 个对象的非静态属性时,不会导致其他对象中同样的属性值的修改
    静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态 变量 时,会导致其他对象调用此静态变量时,是修改过了的
    3.2static修饰属性的其他说明:
    ①静态变量随着类的加载而加载。可以通过“类.静态变量”的方式进行调用
    ②静态变量的加载要早于对象的创建。
    ③由于类只会加载一次,则静态变量在内存中也只会存在一份
    ④ 类变量 实例变量
    类 yes no
    对象 yes yes
    3.3静态属性举例:System.out;Math.PI;

QQ截图20211224183609.png

4、使用static修饰方法:静态方法
①随着类的加载而加载,可以通过“类.静态方法”的方式进行调用
② 静态方法 非静态方法
类 yes no
对象 yes yes
③静态方法中,只能调用静态的方法或属性
非静态方法中,既可以调用非静态的方法和属性,也可以调用静态的方法和属性
因为生命周期不同
5、static注意点:
5.1在静态的方法内,不能使用this关键字、super关键字
5.2关于静态属性和静态方法的使用,大家都从生命周期的角度去理解

6、 开发中,如何确定一个属性是否要声明为static的?
>属性是可以被多个对象所共享的,不会随着对象的不同而不同的。
>类中的常量也常常声明为static
开发中,如何确定一个方法是否要声明为static的?
>操作静态属性的方法,通常设置为static的
>工具类中的方法,习惯上声明为static的。比如:Math Arrays Collection


静态方法如果要访问该类中的非静态成员,需要在静态方法中创建一个对象,通过对象来调用

3、单例 (Singleton)设计模式

设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模免去我们自己再思考和摸索。就像是经典的棋谱,不同的棋局,我们用不同的棋谱。”套路”

所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。

3.1 单例(Singleton)设计模式-饿汉式

QQ截图20211224213912.png

3.2 单例(Singleton)设计模式-懒汉式

QQ截图20211224214155.png

3.3 区分饿汉式和懒汉式

饿汉式:
坏处:对象加载时间过长
好处:饿汉式是线程安全的
懒汉式:
好处:延迟对象的创建
坏处:线程不安全——>到多线程内容时,再修改

4、理解main方法的语法(了解)

main()方法的使用说明
1、main()方法作为程序的入口
2、main()方法也是一个普通的静态方法
3、main()方法可以作为我们与控制台交互的方式。(之前,使用Scanner)

5、类的成员之四:代码块

或称为初始化块
1、代码块作用:用来初始化类、对象
2、代码块如果有修饰的话,只能使用static
3、分为:静态代码块 VS 非静态代码块

4、静态代码块
>内部可以有输出语句
>随着类的加载而执行,而且只执行一次
>作用:初始类的信息
>若有多个静态的代码块,那么按照从上到下的顺序依次执行。
>静态代码块的执行优先于非静态的代码块
>静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构

5、非静态代码块
>内部可以有输出语句
>随着对象的创建而执行
>每创建一个对象,就执行一次非静态代码块
>作用:可以在创建对象时,对对象的属性等进行初始化
>若有多个非静态的代码块,那么按照从上到下的顺序依次执行。
>非静态的代码块的执行要优先于构造器
>非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法
开发中一般就一个代码块

对属性可以赋值的位置:
①默认初始化
②显示初始化、⑤在代码块中赋值
③构造器中初始化
④有了对象以后,可以通过“对象.属性”或“对象.方法”的方式,进行赋值
执行顺序:
QQ截图20211226202000.png


总结:由父及子,静态先行

  1. package com.atguigu.java3;
  2. class Root{
  3. static{
  4. System.out.println("Root的静态初始化块");
  5. }
  6. {
  7. System.out.println("Root的普通初始化块");
  8. }
  9. public Root(){
  10. System.out.println("Root的无参数的构造器");
  11. }
  12. }
  13. class Mid extends Root{
  14. static{
  15. System.out.println("Mid的静态初始化块");
  16. }
  17. {
  18. System.out.println("Mid的普通初始化块");
  19. }
  20. public Mid(){
  21. System.out.println("Mid的无参数的构造器");
  22. }
  23. public Mid(String msg){
  24. //通过this调用同一类中重载的构造器
  25. this();
  26. System.out.println("Mid的带参数构造器,其参数值:"
  27. + msg);
  28. }
  29. }
  30. class Leaf extends Mid{
  31. static{
  32. System.out.println("Leaf的静态初始化块");
  33. }
  34. {
  35. System.out.println("Leaf的普通初始化块");
  36. }
  37. public Leaf(){
  38. //通过super调用父类中有一个字符串参数的构造器
  39. super("尚硅谷");
  40. System.out.println("Leaf的构造器");
  41. }
  42. }
  43. public class LeafTest{
  44. public static void main(String[] args){
  45. new Leaf();
  46. //new Leaf();
  47. }
  48. }
  49. Root的静态初始化块
  50. Mid的静态初始化块
  51. Leaf的静态初始化块
  52. Root的普通初始化块
  53. Root的无参数的构造器
  54. Mid的普通初始化块
  55. Mid的无参数的构造器
  56. Mid的带参数构造器,其参数值:尚硅谷
  57. Leaf的普通初始化块
  58. Leaf的构造器
  1. package com.atguigu.java3;
  2. class Father {
  3. static {
  4. System.out.println("11111111111");
  5. }
  6. {
  7. System.out.println("22222222222");
  8. }
  9. public Father() {
  10. System.out.println("33333333333");
  11. }
  12. }
  13. public class Son extends Father {
  14. static {
  15. System.out.println("44444444444");
  16. }
  17. {
  18. System.out.println("55555555555");
  19. }
  20. public Son() {
  21. System.out.println("66666666666");
  22. }
  23. public static void main(String[] args) { // 由父及子 静态先行
  24. System.out.println("77777777777");
  25. System.out.println("************************");
  26. new Son();
  27. System.out.println("************************");
  28. new Son();
  29. System.out.println("************************");
  30. new Father();
  31. }
  32. }
  33. 11111111111
  34. 44444444444
  35. 77777777777
  36. ************************
  37. 22222222222
  38. 33333333333
  39. 55555555555
  40. 66666666666
  41. ************************
  42. 22222222222
  43. 33333333333
  44. 55555555555
  45. 66666666666
  46. ************************
  47. 22222222222
  48. 33333333333

存在继承的情况下,初始化顺序为:

  • 父类(静态变量、静态语句块)
  • 子类(静态变量、静态语句块)
  • 父类(实例变量、普通语句块)
  • 父类(构造函数)
  • 子类(实例变量、普通语句块)
  • 子类(构造函数)

    6、关键字:final

    final:最终的;
    1、final可以用来修饰的结构:类、方法、变量

2、final 用来修饰一个类:此类不能被其他类所继承
比如:String类、System类、StringBuffer类

3、final 用来修饰一个方法:方法不能被子类重写。
比如:Object类中的getClass()。

4、final 用来修饰一个变量:此时的“变量”就称为是一个常量
4.1 final修饰一个属性:可以考虑赋值的位置有:显示初始化、代码块中初始化、构造器中初始化
4.2 final修饰一个局部变量:
尤其是使用final修饰形参时,表明此形参是一个常量,当我们调用此方法时,给常量形参赋一个实 参, 一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值。

static final:用来修饰属性,全局常量
QQ截图20211227093440.png
private 方法隐式地被指定为 final,如果在子类中定义的方法和基类中的一个 private 方法签名相同,此时子类的方法不是重写基类方法,而是在子类中定义了一个新的方法。

尚硅谷宋红康第6章_面向对象编程(下).pdf
拓展:工厂设计模式.pdf