Java基础笔记(面向对象高级)

8 面向对象(高级)

8.1 类变量和类方法⭐️

8.1.1 类变量

  • 基本介绍:

    类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量

  • 基本语法:
    访问修饰符 static 数据类型 变量名;
    static 访问修饰符 数据类型 变量名;
    
  • 如何访问类变量:
    1. 类名.类变量名
    2. 对象名.类变量名
    3. 静态变量的访问修饰符的访问权限和范围和普通属性是一样的
  • 内存布局:
  • 注意事项和细节:
    1. 类变量是该类的所有对象共享的,而实例变量是每个对象独享的
    2. 加上static称为类变量或静态变量,否则称为实例变量/普通变量/非静态变量
    3. 类变量可以通过 类名.类变量名 或者 对象名.类变量名来访问
    4. 实例变量不能通过类名.类变量名方式访问
    5. 类变量是在类加载时就初始化
    6. 类变量的生命周期是随类的加载开始,随着类消亡而销毁

8.1.2 类方法

  • 基本介绍:

    类方法也叫静态方法

  • 基本语法:
    访问修饰符 static 数据返回类型 方法名(){};
    static 访问修饰符 数据返回类型 方法名(){};
    
  • 类方法调用:
    1. 类名.类方法名
    2. 对象名.类方法名
    3. 满足访问修饰符的访向权限和范围
  • 使用场景:
    1. 当方法中不涉及到任何和对象相关的成员,则可以将方法设计成静态方法,提高开发效率
    2. 程序员实际开发,往往会将一些通用的方法,设计成静态方法,这样我们不需要创建对象就可以使用
  • 注意事项和细节:
    1. 类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区:
      类方法中无this的参数,普通方法中隐含着this的参数
    2. 类方法可以通过类名调用,也可以通过对象名调用
    3. 普通方法和对象有关,需要通过对象名调用,比如对象名.方法名(参数),不能通过类名调用
    4. 类方法中不允许使用和对象有关的关键字,比如this和super
    5. 静态方法,只能访问静态的成员,非静态的方法,可以访问静态成员和非静态成员

8.2 main方法

  • 深入理解main方法:
    1. java虛拟机需要调用类的main0方法,所以该方法的访问权限化须是public
    2. java虚拟机在执行main0方法时不必创建对象,所以该方法心须是static
    3. 该方法接收String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数
    4. java 执行的程序 参数1 参数2 参数3
  • 注意事项和细节:
    1. 在main()方法中,我们可以直接调用main方法所在类的静态方法或静态属性
    2. 但是,不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的目静态成员

8.3 代码块

  • 基本介绍:

    代码化块又称为初始化块,属于类中的成员,类似于方法,将逻辑语句封装在方法体中,通过们包围起来。但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显式调用,而是加载类时,或创建对象时隐式调用

  • 基本语法:
    [修饰符]{
      代码;
    }
    
  • 注释:
    1. 修饰符 可选,要写的话,也只能写 static
    2. 代码块分为两类,使用static 修饰的叫静态代码块,没有static修饰的,叫普通代码块
    3. 逻辑语句可以为任何逻辑语句
    4. :号可以写上,也可以省略
  • 注意事项和细节:
    1. static代码块是类加载时执行,且只会执行一次
    2. 普通代码块是在创建对象的调用的,创建一次,调用一次
    3. 类什么时候被加载⭐️⭐️:
      • 创建对象实例时
      • 创建子类对象实例时,父类也会被加载
      • 使用类的静态成员时
    4. 创建一个对象时,在一个类的调用顺序
      • 调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级样,如果有多个静态代码块和多个静
        态变量初始化,则按他们定义的顺序调
      • 调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,若果有多个普通代码块和stat多个普通属性初始化,则按定义顺序调用)
      • 调用构造器
    5. 构造方法(构造器)的最前面其实隐含了 super()和调用普通代码块
    6. 创建子类时顺序⭐️⭐️:
      • 父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
      • 子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
      • 父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
      • 父类构造方法
      • 子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
      • 子类构造方法
    7. 静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员

8.4 单例设计模式

  • 基本介绍:

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

    单例模式有两种方式:1. 饿汉式 2.懒汉式

  • 饿汉式:
    1. 构造器私有化

    2. 类的内部创建静态对象

    3. 向外暴露一个静态公共方法

    4. 特点:在类加载的时候就创建对象实例,可能存在资源浪费

      class GirlFriend{
          private String name;
      
          private static GirlFriend gf = new GirlFriend("小花");
      
          private GirlFriend(String name) {
              this.name = name;
          }
      
          public static GirlFriend Instance() {
              return gf;
          }
      }
      
  • 懒汉式:
    1. 构造器私有化

    2. 定义一个static静态属性对象

    3. 提供一个public的static方法,返回一个对象

    4. 只有当使用(3)的方法时,才返回对象,再次调用时,返回上次创建的对象

    5. 特点:线程安全问题

      class Cat{
          private String name;
          private static Cat cat;
      
          private Cat(String name) {
              this.name = name;
          }
      
          public static Cat getInstance(){
              if(cat == null){
                  cat = new Cat("小花");
              }
              return cat;
          }
      }
      
  • 对比:
    1. 最主要的区别在于创建对象的时机不同:饿汉式是在类加载就创建了对象实例,而懒汉式是在使用时才创建
    2. 饿汉式不存在线程安全问题,徽汉式存在线程安全问题
    3. 饿汉式存在浪费姿源的可能,对象实例都没有使用,那么饿汉式创建的对象就浪费,懒汉式是使用时才创建,就不存在这个问题

8.5 final

  • 基本介绍:
    • final可以修饰类、属性、方法、局部变量

    • final 类,类不能被继承

    • final 方法,子类无法重写方法

    • final 属性,属性无法被修改

    • final 局部变量,局部变量无法被修改

  • 注意事项和细节:
    1. final修饰的属性又叫常量,一般用XX_XX_XX 来命名
    2. final修饰的属性在定义时,必须赋初值,并且以后不能再修改,赋值可以在如下位置:
      定义时、构造器、代码块
    3. final修饰的属性是静态的,则初始化的位置只能是:定义时、静态代码块
    4. final类不能继承,但可以实例化对象
    5. 如果类不是final类,但是含有final方法,则该方法虽然不能重写,但是可以被继承
    6. 如果一个类已经是final类了,就没有必要再将方法修饰成final方法
    7. final不能修饰构造器本身
    8. final 和static 往往搭配使用,效率更高,不会导致类加载-底层编译器做了优化处理
    9. 包装类(Integer, Double,Float,Boolean等都是final),String也是final类

8.6 抽象类

  • 基本介绍:
    • 用abstract 关键字来修饰一个类时,这个类就叫抽象类

    • 用abstract 关键字来修饰一个方法时,这个方法就是抽象方法,没有方法体

    • 抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类

  • 注意事项和细节:
    1. 抽象类不能被实例化
    2. 抽象类可以没有abstract方法
    3. 一旦类包含了abstract方法,则这个类必须声明为abstract
    4. abstract 只能修饰类和方法
    5. 抽象类可以有任意成员,抽象类本质还是类
    6. 抽象方法不能有主体
    7. 如果一个类继承了抽象类,则它必须实现抽象类的所有的抽象方法,除非它自己也声明为abstract类
    8. 抽象方法不能使用private、final 和static来修饰,因为这些关键字都是和重写相违背的
  • 抽象类模版设计模式:
    1. 编写方法cal(),可以计算某段代码的耗时时间
    2. 编写抽象方法job()
    3. 编写一个子类A,继承抽象类Template,井实现job方法
    4. 编写一个测试类TestTemplate,看看是否好用
    public class TextTemplate {
        public static void main(String[] args) {
            A a = new A();
            a.cal();
    
            B b = new B();
            b.cal();
        }
    }
    
    abstract public class Template {
    
        public abstract void job();
    
        public void cal() {
                long start = System.currentTimeMillis();
                job();
                long end = System.currentTimeMillis();
                System.out.println("时间" + (end - start));
        }
    }
    
    
    class A extends Template{
    
        public void job() {
            long num = 0;
            for (long i = 0; i <= 10000000; i++) {
                num += i;
            }
        }
    }
    
    class B extends Template{
    
        public void job() {
            long num = 0;
            for (long i = 0; i <= 10000000; i++) {
                num *= i;
            }
        }
    }
    

8.7 接口⭐️

  • 基本介绍:

    接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体情况把这些方法写出来

  • 基本语法:
    interface 接口名{
      //属性
      //方法
    }
    
    class 类名 implements 接口 {
      自己属性;
      自己方法;
      //必须实现接口的抽象方法
    }
    
    1. Jdk7.0前 接口里的所有方法都没有方法体(只能抽象方法)
    2. Jdk8.0后接口类可以有静态方法,defaut实现方法,也就是说接口中可以有方法的具体实现
  • 注意事项和细节:
    1. 接口不能被实例化
    2. 接口中所有的方法是 public 和 abstrac 方法,接口中抽象方法,可以不用 abstract 修饰
    3. 普通类实现接口,就必须将该接口的所有方法实现
    4. 抽象类实现接口,可以不用实现接口的方法
    5. 一个类同时可以实现多个接口
    6. 接口中的属性,只能是 final 的,而且是 public static final 修饰符
    7. 接口中属性的访问形式:接口名.属性名
    8. 一个接口不能继承其它的类,但是可以继承多个别的接口
    9. 接口的修饰符 只能是 public 和 默认,这点和类的修饰符是一样的
  • 实现接口VS继承类:
    1. 继承的价值主要在于:解决代码的复用性和可维护性
    2. 接口的价值主要在于:设计,设计好各种规范(方法),让其它类去实现这些方法
    3. 接口比继承更加灵活,继承是满足 is -a的关系,而接口只需满足 like-a的关系
    4. 接口在一定程度上实现代码解耦
  • 接口类型数组:
    public class InterfacePolyArr {
        public static void main(String[] args) {
    
            //多态数组 -> 接口类型数组
            Usb[] usbs = new Usb[2];
            usbs[0] = new Phone_();
            usbs[1] = new Camera_();
            /*
            给Usb数组中,存放 Phone 和 相机对象,Phone类还有一个特有的方法call(),
            请遍历Usb数组,如果是Phone对象,除了调用Usb 接口定义的方法外,
            还需要调用Phone 特有方法 call
             */
            for(int i = 0; i < usbs.length; i++) {
                usbs[i].work();//动态绑定..
                //和前面一样,我们仍然需要进行类型的向下转型
                if(usbs[i] instanceof Phone_) {//判断他的运行类型是 Phone_
                    ((Phone_) usbs[i]).call();
                }
            }
        }
    }
    
    interface Usb{
        void work();
    }
    class Phone_ implements Usb {
        public void call() {
            System.out.println("手机可以打电话...");
        }
    
        @Override
        public void work() {
            System.out.println("手机工作中...");
        }
    }
    class Camera_ implements Usb {
    
        @Override
        public void work() {
            System.out.println("相机工作中...");
        }
    }
    
    

8.8内部类⭐️

  • 基本介绍:
    • 一个类的内部又完整的嵌套了另一个类结构,被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)
    • 内部类最大的特点就是可以直接访问私有属性,井且可以体现类与类之间的包含关系
  • 基本语法:
    class Outer{//外部类
      class Inner{//内部类
        
      }
    }
    class Other{//外部其他类
      
    }
    
  • 内部类分类:
    1. 定义在外部类局部位置上:1局部类内部(有类名) 2.匿名局部类(没有类名⭐️)
    2. 定义在外部类的成员位置上:1.成员内部类(无static修饰) 2.静态内部类(static修饰)

8.8.1 局部内部类

  • 基本介绍:

    局部内部类是定义在外部类的局部位置,在方法中、代码块中,并且有类名

  • 注意事项和细节:
    1. 可以直接访问外部类的所有成员,包含私有的

    2. 不能添加访问修饰符,但是可以使用final修饰

    3. 作用域:仅仅在定义它的方法或代码块中

    4. 内部类访问外部类:直接访问

    5. 外部类访问内部类:创建对象再访问

    6. 外部其他类访问局部内部类:不能访问

    7. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果访问外部类的成员使用"外部类名.this.成员"去访问

      public class LocalInnerClass {//
      
          public static void main(String[] args) {
              //演示一遍
              Outer02 outer02 = new Outer02();
              outer02.m1();
              System.out.println("outer02的hashcode=" + outer02);
          }
      }
      
      
      class Outer02 {//外部类
          private int n1 = 100;
      
          private void m2() {
              System.out.println("Outer02 m2()");
          }//私有方法
      
          public void m1() {//方法
              //1.局部内部类是定义在外部类的局部位置,通常在方法
              //3.不能添加访问修饰符,但是可以使用final 修饰
              //4.作用域 : 仅仅在定义它的方法或代码块中
              final class Inner02 {//局部内部类(本质仍然是一个类)
                  //2.可以直接访问外部类的所有成员,包含私有的
                  private int n1 = 800;
      
                  public void f1() {
                      //5. 局部内部类可以直接访问外部类的成员,比如下面 外部类n1 和 m2()
                      //7. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,
                      //   使用 外部类名.this.成员)去访问
                      //    Outer02.this 本质就是外部类的对象, 即哪个对象调用了m1, Outer02.this就是哪个对象
                      System.out.println("n1=" + n1 + " 外部类的n1=" + Outer02.this.n1);
                      System.out.println("Outer02.this hashcode=" + Outer02.this);
                      m2();
                  }
              }
              //6. 外部类在方法中,可以创建Inner02对象,然后调用方法即可
              Inner02 inner02 = new Inner02();
              inner02.f1();
          }
      }
      

8.8.2 匿名内部类⭐️⭐️

  • 基本介绍:

    匿名内部类是定义在外部类的局部位置,比如方法中,并目没有类名,同时还是一个对象

  • 基本语法:
    new 类或接口(参数列表){
      类体;
    };
    
  • 底层:
    1. 本质: IA tiger = class Xxxx$1 class Xxxx$1 = new IA
    2. 接口的底层:class Xxxx$1 implement IA{@Overide}
    3. 本质: Father father = class Xxxx$2 class Xxxx$2 = new Father
    4. 类的底层:class Xxxx$2 extends Father{@Overide}
  • 注意事项和细节:
    1. 匿名内部类既是一个类的定义同时本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征

    2. 可以直接访问外部类的所有成员,包含私有的

    3. 不能添加访问修饰符,因为它的地位就是一个局部变量

    4. 作用域:仅仅在定义它的方法或代码块中

    5. 匿名内部类方位外部类成员:直接访问

    6. 外部其他类访问匿名内部类:不能访问

    7. 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员)去访问

      public class AnonymousInnerClass {
          public static void main(String[] args) {
              Outer04 outer04 = new Outer04();
              outer04.method();
          }
      }
      
      class Outer04 { //外部类
          private int n1 = 10;//属性
          public void method() {//方法
              //基于接口的匿名内部类
              //
              //1.需求: 想使用IA接口,并创建对象
              //2.传统方式,是写一个类,实现该接口,并创建对象
              //3.需求是 Tiger/Dog 类只是使用一次,后面再不使用
              //4. 可以使用匿名内部类来简化开发
              //5. tiger的编译类型 ? IA
              //6. tiger的运行类型 ? 就是匿名内部类  Outer04$1
              /*
                  我们看底层 会分配 类名 Outer04$1
                  class Outer04$1 implements IA {
                      @Override
                      public void cry() {
                          System.out.println("老虎叫唤...");
                      }
                  }
               */
              //7. jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1实例,并且把地址
              //   返回给 tiger
              //8. 匿名内部类使用一次,就不能再使用
              IA tiger = new IA() {
                  @Override
                  public void cry() {
                      System.out.println("老虎叫唤...");
                  }
              };
              System.out.println("tiger的运行类型=" + tiger.getClass());
              tiger.cry();
      
      //        IA tiger = new Tiger();
      //        tiger.cry();
      
              //演示基于类的匿名内部类
              //分析
              //1. father编译类型 Father
              //2. father运行类型 Outer04$2
              //3. 底层会创建匿名内部类
              /*
                  class Outer04$2 extends Father{
                      @Override
                      public void test() {
                          System.out.println("匿名内部类重写了test方法");
                      }
                  }
               */
              //4. 同时也直接返回了 匿名内部类 Outer04$2的对象
              //5. 注意("jack") 参数列表会传递给 构造器
              Father father = new Father("jack"){
      
                  @Override
                  public void test() {
                      System.out.println("匿名内部类重写了test方法");
                  }
              };
              System.out.println("father对象的运行类型=" + father.getClass());//Outer04$2
              father.test();
      
              //基于抽象类的匿名内部类
              Animal animal = new Animal(){
                  @Override
                  void eat() {
                      System.out.println("小狗吃骨头...");
                  }
              };
              animal.eat();
          }
      }
      
      interface IA {//接口
          public void cry();
      }
      //class Tiger implements IA {
      //
      //    @Override
      //    public void cry() {
      //        System.out.println("老虎叫唤...");
      //    }
      //}
      //class Dog implements  IA{
      //    @Override
      //    public void cry() {
      //        System.out.println("小狗汪汪...");
      //    }
      //}
      
      class Father {//类
          public Father(String name) {//构造器
              System.out.println("接收到name=" + name);
          }
          public void test() {//方法
          }
      }
      
      abstract class Animal { //抽象类
          abstract void eat();
      }
      
      public class LocalInnerClassDetail {
          public static void main(String[] args) {
              Outer03 outer03 = new Outer03();
              outer03.f1();
          }
      }
      
      class Outer03{
          private int n1 = 99;
          public void f1(){
              Person person = new Person(){
                  @Override
                  public void hi() {
                      System.out.println("匿名内部类重写hi方法");
                  }
              };
              person.hi();
      
              new Person(){
                  @Override
                  public void hi() {
                      System.out.println("匿名内部类重写ok方法");
                  }
      
                  @Override
                  public void ok(String str) {
                      super.ok(str);
                  }
              }.ok("jack");
          }
      }
      
      class Person{
          public void hi(){
              System.out.println("Person hi()");
          }
      
          public void ok(String str){
              System.out.println("Person ok()"+str);
          }
      }
      
      public class InnerClassExercise02 {
          public static void main(String[] args) {
              CellPhone cellPhone = new CellPhone();
              cellPhone.alarmclock(new Bell(){
                  public void ring(){
                      @Override
                      System.out.println("懒猪起床");
                  }
              });
          }
      }
      
      interface Bell{
          void ring();
      }
      
      class CellPhone{
          public void alarmClock(Bell bell){
              bell.ring();
          }
      }
      

8.8.3 成员内部类

  • 基本介绍:

    成员内部类是定义在外部类的成员位置,并且没有static修饰

  • 注意事项和细节:
    1. 可以直接访问外部类的所有成员,包含私有的

    2. 可以添加任意访问修饰符

    3. 作用域:为整个外部类类体

    4. 成员内部类访问外部类:直接访问

    5. 外部类访问成员内部类;创建对象,再访问

    6. 外部其他类访问成员内部类:

      • 外部类.内部类 引用名 = 外部对象.new 内部类();

      • 外部类.内部类 引用名 = 外部对象.get();

    7. 如果外部类和成员内部类的成员重名时,成员内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员)去访问

      public class MemberInnerClass01 {
          public static void main(String[] args) {
              Outer08 outer08 = new Outer08();
              outer08.t1();
      
              //外部其他类,使用成员内部类的三种方式
              //
              // 第一种方式
              // outer08.new Inner08(); 相当于把 new Inner08()当做是outer08成员
              // 这就是一个语法,不要特别的纠结.
              Outer08.Inner08 inner08 = outer08.new Inner08();
              inner08.say();
              // 第二方式 在外部类中,编写一个方法,可以返回 Inner08对象
              Outer08.Inner08 inner08Instance = outer08.getInner08Instance();
              inner08Instance.say();
          }
      }
      
      class Outer08 { //外部类
          private int n1 = 10;
          public String name = "张三";
      
          private void hi() {
              System.out.println("hi()方法...");
          }
      
          //1.注意: 成员内部类,是定义在外部内的成员位置上
          //2.可以添加任意访问修饰符(public、protected 、默认、private),因为它的地位就是一个成员
          public class Inner08 {//成员内部类
              private double sal = 99.8;
              private int n1 = 66;
      
              public void say() {
                  //可以直接访问外部类的所有成员,包含私有的
                  //如果成员内部类的成员和外部类的成员重名,会遵守就近原则.
                  //,可以通过  外部类名.this.属性 来访问外部类的成员
                  System.out.println("n1 = " + n1 + " name = " + name + " 外部类的n1=" + Outer08.this.n1);
                  hi();
              }
          }
      
          //方法,返回一个Inner08实例
          public Inner08 getInner08Instance() {
              return new Inner08();
          }
          
          //写方法
          public void t1() {
              //使用成员内部类
              //创建成员内部类的对象,然后使用相关的方法
              Inner08 inner08 = new Inner08();
              inner08.say();
              System.out.println(inner08.sal);
          }
      }
      

8.8.4 静态内部类

  • 基本介绍:

    静态内部类是定义在外部类的成员位置,并且有static修饰

  • 注意事项和细节:
    1. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员

    2. 可以添加任意访问修饰符

    3. 作用域:整个外部类类体

    4. 静态内部类访问外部类:直接访问

    5. 外部类访问静态内部类:创建对象,再访问

    6. 外部其他类访问静态内部类:

      • 外部类.内部类 引用名 = new 外部类.内部类();

      • 外部类.内部类 引用名 = 外部对象.get();

      • 外部类.内部类 引用名 = 外部类.get();

    7. 如果外部类和静态内部类的成员重名时,静态内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员)去访问

      public class StaticInnerClass01 {
          public static void main(String[] args) {
              Outer10 outer10 = new Outer10();
              outer10.m1();
      
              //外部其他类 使用静态内部类
              //方式1
              //因为静态内部类,是可以通过类名直接访问(前提是满足访问权限)
              Outer10.Inner10 inner10 = new Outer10.Inner10();
              inner10.say();
              //方式2
              //编写一个方法,可以返回静态内部类的对象实例.
              Outer10.Inner10 inner101 = outer10.getInner10();
              System.out.println("============");
              inner101.say();
      
              Outer10.Inner10 inner10_ = Outer10.getInner10_();
              System.out.println("************");
              inner10_.say();
          }
      }
      
      class Outer10 { //外部类
          private int n1 = 10;
          private static String name = "张三";
          private static void cry() {}
          //Inner10就是静态内部类
          //1. 放在外部类的成员位置
          //2. 使用static 修饰
          //3. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
          //4. 可以添加任意访问修饰符(public、protected 、默认、private),因为它的地位就是一个成员
          //5. 作用域 :同其他的成员,为整个类体
          static class Inner10 {
              private static String name = "韩顺平教育";
              public void say() {
                  //如果外部类和静态内部类的成员重名时,静态内部类访问的时,
                  //默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.成员)
                  System.out.println(name + " 外部类name= " + Outer10.name);
                  cry();
              }
          }
      
          public void m1() { //外部类---访问------>静态内部类 访问方式:创建对象,再访问
              Inner10 inner10 = new Inner10();
              inner10.say();
          }
      
          public Inner10 getInner10() {
              return new Inner10();
          }
      
          public static Inner10 getInner10_() {
              return new Inner10();
          }
      }
      

8.9 类加载顺序⭐️⭐️

  • 类什么时候被加载:
    • 创建对象实例时
    • 创建子类对象实例时,父类也会被加载
    • 使用类的静态成员时
  • 创建一个对象时,在一个类的调用顺序
    1. 调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级样,如果有多个静态代码块和多个静

      态变量初始化,则按他们定义的顺序调)

    2. 调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,若果有多个普通代码块和多个普通属性初始化,则按定义顺序调用)

    3. 调用构造方法

  • 创建子类时顺序:
    1. 父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
    2. 子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
    3. 父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
    4. 父类构造方法
    5. 子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
    6. 子类构造方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恐高宇航员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值