• on java8之复用


    复用有两种方式,组合和继承

    1. 组合

    在新类中创建现有类的对象。这种方式叫做 “组合”(Com-position),通过这种方式复用代码的功能,而非其形式

    class WaterSource {
      private String s;
      WaterSource() {
        System.out.println("WaterSource()");
        s = "Constructed";
      }
      @Override public String toString() { return s; }
    }
    
    public class SprinklerSystem {
      private String valve1, valve2, valve3, valve4;
      private WaterSource source = new WaterSource();
      private int i;
      private float f;
      @Override public String toString() {
        return
          "valve1 = " + valve1 + " " +
          "valve2 = " + valve2 + " " +
          "valve3 = " + valve3 + " " +
          "valve4 = " + valve4 + "\n" +
          "i = " + i + " " + "f = " + f + " " +
          "source = " + source;                      // [1]
      }
      public static void main(String[] args) {
        SprinklerSystem sprinklers = new SprinklerSystem();
        System.out.println(sprinklers);
      }
    }
    /* Output:
    WaterSource()
    valve1 = null valve2 = null valve3 = null valve4 = null
    i = 0 f = 0.0 source = Constructed
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    2. 继承

    继承是所有面向对象语言的一个组成部分。事实证明,在创建类时总是要继承,因
    为除非显式地继承其他类,否则就隐式地继承 Java 的标准根类对象(Object)

    继承的父类子类的构造顺序:

    class Art {
      Art() {
        System.out.println("Art constructor");
      }
    }
    
    class Drawing extends Art {
      Drawing() {
        System.out.println("Drawing constructor");
      }
    }
    
    public class Cartoon extends Drawing {
      public Cartoon() {
      //super(); 这句调用隐藏了
        System.out.println("Cartoon constructor");
      }
      public static void main(String[] args) {
        Cartoon x = new Cartoon();
      }
    }
    /* Output:
    Art constructor
    Drawing constructor
    Cartoon constructor
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    继承时的各个类的构造顺序为:从最高层的父类依次往下进行构造

    注意一个问题,上面的Drawing类的构造方法中其实隐式地调用了父类Carton地无参构造方法,假设给Craton类只定义一个有参构造方法,则编译器不会给Carton类提供一个默认的构造方法,此时必须在Drawing的构造方法中显示地调用Carton类的有参构造方法

    class Carton{
        public Carton(int i){
            System.out.println("Carton 类的有参构造方法");
        }
    }
    public class Drawing extends Carton {
            public Drawing(){
                super(1);//必须加上这一句 否则编译错误
                System.out.println("Drawing 类的无参构造方法");
            }
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    方法重写和变量覆盖:

    class Carton{
        String name="Carton";
        public void print(){
            System.out.println("Carton");
        }
    }
    public class Drawing extends Carton {
           
        String name="Drawing";
        public void print(){
            System.out.println("Drawing");
        }
        public void newMethod(){
            System.out.println("newMethod");
        }
        public static void main(String[] args){
            Carton c=new Drawing();
            System.out.println(c.name);//Carton
            c.print();//Drawing
           // c.newMethod();//编译错误 父类中没有newMethod方法
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    当引用变量是父类类型,创建的对象的子类类型时,调用的变量时父类的,调用的重载的方法是子类的


    3. final关键字

    1. final修饰基本类型时,必须在定义常量的时候进行赋值或代码块中或构造器中赋值,该基本类型的值后面不能被改变
    final int a=1;//ok
    final int a; a=1;//not ok
    final int a;
      {
           a=1;//ok
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. final修饰引用类型时,引用变量不能再指向其他的对象,但是对象里面的数据可以改变
    final Apple apple=new Appale();
    appple=new Apple();//not ok
    apple.price=2.2;//ok
    
    • 1
    • 2
    • 3

    final修饰方法和类:

    • fianl修饰的方法不能被子类重写覆盖
    • 类中所有的 private 方法都隐式地指定为 final, private方法不能被子类访问,因此不能被重写,注意一点,如果父类的中的方法只是被private修饰,在子类中依然可以定义一个具有相同方法签名的方法,此时不是重写,而是在子类中创建了一个新的方法,与父类中的方法没有关系
    • 一个类是 final (final 关键字在类定义之前),就意味着它不能被继承

    4. 类初始化和加载

    “类的代码在首次使用时加载 “。这通常是指创建类的第一个对象,或者是访问了类的 static 属性或方法。构造器也是一个 static 方法尽管它的 static 关键字是隐式的

    class Insect {
      private int i = 9;
      protected int j;
      Insect() {
        System.out.println("i = " + i + ", j = " + j);
        j = 39;
      }
      private static int x1 = printInit("static Insect.x1 initialized");
      static int printInit(String s) {
        System.out.println(s);
        return 47;
      }
    }
    
    public class Beetle extends Insect {
      private int k = printInit("Beetle.k initialized");
      public Beetle() {
        System.out.println("k = " + k);
        System.out.println("j = " + j);
      }
      private static int x2 =printInit("static Beetle.x2 initialized");
      public static void main(String[] args) {
        System.out.println("Beetle constructor");
        Beetle b = new Beetle();
      }
    }
    /* Output:
    static Insect.x1 initialized
    static Beetle.x2 initialized
    Beetle constructor
    i = 9, j = 0
    Beetle.k initialized
    k = 47
    j = 39
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    1. 加载Beetle类,发现Beetle类有一个基类,于是先加载基类,加载基类时不论是否创建了基类的对象
    2. 父类的静态初始化操作
    3. 子类的静态初始化操作
    4. 类加载完成,开始对象创建
    5. 先创建父类的对象: 1. 父类对象中的所有基本类型变量都被置为默认值,对象引用被设为 null 2.调用基类的构造器(基本类型和引用类型的显示赋值实际上会被提取到构造器方法中,代码块中的显示赋值语句也会被提取到构造器中)
    6. 创建子类的对象,过程和创建父类的对象相同

    总结:

    1. 静态代码块比非静态代码块先执行
    2. 静态变量只会分配一次空间,静态代码块只会执行一次
    3. 代码块中的语句比构造器中的语句先执行(可以看出将代码块中的语句提到构造器中的前面部分)
    4. 变量值的变化: 分配空间和默认值->显示指定的值(如果定义时指定值和代码块中指定值同时存在,按定义的值和代码块的相对位置来判断,最后更新的值为最终的值)->构造器方法中指定的值->普通方法中指定的值
  • 相关阅读:
    如何自动识别爬虫网页的编码
    nvme安装
    桌面下雪小程序
    16:00面试,16:06就出来了,问的问题有点变态。。。
    深入探讨医保购药APP的技术架构与设计思路
    XSS脚本(存储型xss获取肉鸡的cookies)
    开发者说论文|人工智能为设备磨损“把脉”:依托飞桨开展的铁谱图像智能故障诊断研究...
    Pandas里的Series学习
    IDEA——工程项目的两种窗口开发模式
    Java杨辉三角,内存优化版本
  • 原文地址:https://blog.csdn.net/qq_43478694/article/details/126498335