2022-7-27 第八组-曹雨-面向对象

代码块

类的内部结构:
属性、方法、、构造器、代码块、内部类

代码块:

  • 代码块又称为初始化块,属于类的一个成员,它是将逻辑语句封装在方法体中。
  • 通过{}包裹。代码块没有方法名,没有参数,没有返回值,只有方法体,
  • 它是不需要通过对象或类进行显式的调用,它会在类加载或者创建对象时
  • 主动的《隐式》调用。

(1)静态代码块:

static {
    // 静态代码块
    System.out.println("静态代码块...");
}

(2)实例代码块:

 {
    // 实例代码块
    System.out.println("实例代码块...");
}

一个类中,静态代码块旨在开始调用,而实例代码块一旦每次调用都会
比如如上代码

   public class Ch01 {

      final String STR;

    static {
        // 静态代码块
        System.out.println("静态代码块...");
    }

    {
        // 实例代码块
        System.out.println("实例代码块...");
    }

    public static void main(String[] args) {
        Ch01 ch01 = new Ch01();
        Ch01 ch02 = new Ch01();
      }
    }

运行结果为:

可以看到,静态代码块,只在一开始被调用,而实例代码块每次new一个对象都会被调用

今日面试题:

public class Father {

public Father() {
    System.out.println("父类的构造器...");
}
{
    System.out.println("父类的实例块...");
}
static {
    System.out.println("父类的静态块...");
}

public static void main(String[] args) {
    Father father = new Father();
}

在一个类中,当同时有构造器,实例块,静态块时。谁先被调用,谁后被调用。
程序运行结果为:


可以看到静态块依然最先被调用,实例块紧随其后,构造器最后被调用。

此时加入一个Ch02继承于Father,它同样有自己的构造器,静态块,实例块。创建子类对象后,是什么顺序。

public class Ch02 extends Father {

public Ch02() {
    System.out.println("子类的构造器...");
}
{
    System.out.println("子类的实例块...");
}
static {
    System.out.println("子类的静态块...");
}

public static void main(String[] args) {
    new Ch02();
}

}
结果是:

一般规律是:
父亲>孩子
静态块>实力块>构造器

结论:
  • 当没有继承关系,就一个类,静态块---实力块---构造器
  • 当有继承关系,父类静态块---子类静态块---父类实力块---父类构造器---子类实力块---子类构造器

静态 static(也可以叫类属性,类方法)

可以修饰属性,方法,代码块

修饰属性(方法和代码块同理)

    public class Ch03 {

    static String name = "里奥·梅西";
 }
  按照传统方式:
    Ch03 ch03 = new Ch03();
    ch03.name;
  如果这个属性前面有“static”我就可以直接用“类名.name”
    Ch03.name;来调用

用“static”修饰的属性不属于任何一个对象,直接属于一个类。我可以直接通过类名去调

static内存解析:

  • 1、静态的变量或者静态方法存在于方法区的。静态的结构不会被垃圾回收。
  • 2、不属于某一个实例对象,只存在于方法区。调用静态结构,直接用类名.的方式。

Java的垃圾回收机制:

int a = 20;
这个a使用完成后,JVM会自动回收

而如果你是静态变量

static a = 20;
不会回收。
 static修饰的变量都储存在“方法区”中。

实例方法与静态方法的互相调用

创建一个实例方法

  public void fun(){
}

在静态方法中对其进行调用

    public static void show(){
          fun();
}

是不可以的,会报错:

正确的方式是

    public static void show(){
        Ch03().fun();

}

1、静态方法中可以直接调用实例方法吗?

  • 不可以!!!如果想用,必须对象.方法名

2、实例方法中可以直接调用静态方法吗?

  • 可以!!!

静态的结构的加载,随着类的加载而加载!!!
非静态的结构,随着对象的创建而加载!!

出现顺序

静态 先于 非静态

实例方法不能单独调用,必须通过对象调
静态方法不管在哪都是“类名.方法名”

静态方法没有重写这个概念的!

this和super
  • 无论是this还是super,都不可以在静态结构中使用。

  • this和super。this.方法。super.方法

  • 静态结构是属于类的,静态结构是优先于对象就存在的。

  • this和super,必须有对象才能出现。必须得有实例。

外部类

  • 一个public声明的类,类名必须和.java的文件名相同。

  • 生成的.class文件是两个独立的.class

  • 外部类就是两个类。正常使用

  • 开发中,尽量不要写外部类。

     public class Ch05 {
    
         int i = 10;
    
         public static void main(String[] args) {
    
         }
     }
       class Outer {
           public static void main(String[] args) {
    
         }
     }
    

设计模式:

程序设计师之间沟通的“行话”

面向对象的设计原则:

1、开闭原则(Open Close Principle)
  • 对扩展开放,对修改关闭。(继承,实现接口)
  • 我们可以通过“抽象约束,封装变化”来实现开闭原则。
  • 通过接口或者抽象类为软件定义一个相对稳定的抽象层。
  • 将相同的可变因素封装在相同的具体实现类中。派生一个实体类就可以了。
2、里氏代换原则
  • 子类继承父类时,除了添加新的方法完成新增的功能外,尽量不要重写父类的方法
3、依赖倒转原则
  • 要面向接口编程,不要面向实现编程。
    a、每个类尽量提供接口或抽象类,或者两者兼备
    b、变量的类型声明尽量是接口或者是抽象类
    c、任何类都不应该从具体类派生
    d、使用继承时,要遵循里氏代换原则。
4、接口隔离原则
  • 使用多个隔离的接口。
5、迪米特法则
6、合成复用原则
7、单一原则:一个类只做一件事

单例模式(一个类只有一个实例):

基本思路:
  • 别人不能new,构造器私有化,不能在类的外部通过new去实例化
  • 在该类内部产生一个唯一的实例对象,把它封装成static类型
  • 定义一个静态方法返回这个唯一的对象。

饿汉式:

以基本思路为方法,在类中直接创建一个单例对象

  //饿汉式单例模式。
  //不管以后会不会使用到该实例化对象,先创建了再说,很着急的样子。
  //实现的办法就是直接new实例化。
public class Ch03{
    private static final Ch03 ch03 = new Ch03();
    private Ch03(){}
    public static Ch03 getInstance(){return ch03;}
}

懒汉式:

你要用到我,并且类里没有实例对象,我就被你调用。
什么时候调用getInstance方法,什么时候new

public Ch04 {
  //将自身实例化对象设置称为一个属性,此时并没有赋值
  private static Ch04 ch04;

  //将构造器私有化
  private Ch04(){}
  
  public static Ch04 getInstance() {
       
  }

}

posted on 2022-08-11 21:18  figh466  阅读(25)  评论(0)    收藏  举报

导航