Java-03 final、嵌套类、抽象类

Q:子类对象的内存中,是否包含父类中定义的private成员变量?

A:依然包含 private只是降低了访问权限,不影响内存布局和内存分布,外界无法访问,但是子类对象内存中依然包含。子类内存中包含父类所有的成员变量,无论是否是私有的

final

  • 被final修饰的类不能被继承
  • 被final修饰的方法不能被重写
  • 被final修饰的变量,只能进行一次赋值
  • 其他跟在Swift/Flutter中相似

常量

Java中常量一般写成 名称一般大写 static final修饰的称之为常量(约定俗成的叫法,final修饰也可以叫做常量)

private static final int MY_AGE = 1;
  • 如果将基本类型或字符串定义为常量,并且在编译时就能确定值,编译器会使用常量值替换各处的常量名(类似于C语言的宏替换)

嵌套类

  • 嵌套类:定义在另一个类中的类
public class OuterClass {
  // 静态嵌套类 
  static class StaticNestedClass {

  }
  // 非静态嵌套类(内部类)
  class InnerClass {

  }
}
  • 在嵌套类外层的类,称为:外部类(Outer Class)
  • 最外层的外部类,称为:顶级类(Top-level Class)

内部类

内部类:没有被static修饰的嵌套类,非静态嵌套类

  • 跟实例变量,实例方法一样,内部类跟外部类实例相关联,
  • 必须先创建外部类实例,然后通过外部类实例来创建内部类实例
  • 内部类不能定义除了编译时常量以外的任何static成员
  • 内部类可以直接访问外部类的所有成员(即使被声明为private)
  • 外部类可以直接访问内部类实例的成员变量、方法(即使被声明为private)
  • 内部类实例内存中有指向外部类实例的指针

  OuterClass outer = new OuterClass();
  // 通过外部类实例创建内部类实例
  InnerClass inner = outer.new InnerClass();

静态嵌套类(Static Nested Class)

  • 静态嵌套类: 被static修饰的嵌套类
  • 静态嵌套类在行为上就是一个顶层类,只是定义的代码写在了另一个类中
  • 对比一般的顶级类,多了一些权限
    • 可以直接访问外部类中除了实例变量、实例方法之外的其他成员(即使被声明为private)
public class OuterClass {
  private static int count = 1;

  // 静态嵌套类
  static class StaticNestedClass {
    public void run() {
      // 可以访问顶层类的成员 即使是private
      OuterClass.count = 1;
      // 不需要类名也可以直接访问外部类的成员
      System.out.println(count);
    }
  }
}

什么情况使用嵌套类?

  1. 如果类A只在类C中使用,可以考虑把A嵌套在C中

    • 封装性更好
    • 程序包更加简化
    • 增强可读性,维护性
  2. 如果类A需要经常访问类C的非公开成员,可以考虑将A嵌套在C中

    • 也可以考虑将A隐藏起来,不对外暴露
  3. 如果需要经常访问非公共的实例成员,设计成内部类(非静态嵌套类),否则设计成静态嵌套类 (能静态尽量去静态)

局部类

  • 局部类:定义在代码块中的类(可以定义在方法中,for循环中,if语句中等代码块中)

  • 局部类不能定义除了编译时常量以外的任何static成员

  • 局部类只能访问final或者 有效final的局部变量

    • Java 8开始,如果局部变量没有第二次赋值,就认为是有效final
  • 局部类可以直接访问外部类的所有成员(即使被声明为private)

  • 局部类只有被定义在实例相关的代码块中,才能直接访问外部类中的实例成员

public class LocalClass {
  // 实例变量
  public int age = 10;

  // 静态初始化块 在类第一次初始化时调用
  static {
    class A {
      public void test() {
        // 跟实例相关的代码块中的局部类才能访问实例成员
        // 会报错
        // System.out.println(age);
      }
    }
    A a = new A();
    a.test();
  }

  // 初始化块 在类的构造函数中调用
  {
    class A {
      public void test() {
        // 跟实例相关的代码块中的局部类才能访问实例成员
        System.out.println(age);
      }
    }
    A a = new A();
    a.test();
  }

  public void run(){
    // count只赋值一次 被认为是有效fianl
    int count = 0;
    // 再次赋值的话就不被认为是有效final 局部类使用时会报错
    // count = 10;
    // 局部类
    class A {
      // 报错 不能定义除编译时常量以外的static成员 
      // public static int age = 0;
      // 正确
      public static final int age = 10;
      
      public void test() {
        // 可以访问final或者有效final的局部变量
        System.out.println(count);
      }
    }
  }
}

抽象类和抽象方法

  • 抽象方法 :被abstract修饰的方法

    • 只有方法声明,没有方法实现
    • 不能是private权限(因为定义抽象方法的目的就是让子类去实现)
    • 只能是实例方法,不能是类方法
    • 只能定义在抽象类、接口中
  • 抽象类:被abstract修饰的类
    • 可以定义抽象方法
    • 不能实例化,但可以自定义构造函数
    • 子类必须实现抽象父类中的所有抽象方法(除非子类也是一个抽象类)
    • 可以像非抽象类一样定义成员变量,常量,嵌套类,初始化块,非抽象方法等
    • 抽象类也可以完全不定义抽象方法
    • 也就是说,抽象类比非抽象类多了一些抽象方法,但是不能实例化了

跟flutter中的抽象类似

你可能感兴趣的:(Java-03 final、嵌套类、抽象类)