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
*/

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
*/

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

注意一个问题,上面的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 类的无参构造方法");
        }
    
}

方法重写和变量覆盖:

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方法
    }
}

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


3. final关键字

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

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. 加载Beetle类,发现Beetle类有一个基类,于是先加载基类,加载基类时不论是否创建了基类的对象
  2. 父类的静态初始化操作
  3. 子类的静态初始化操作
  4. 类加载完成,开始对象创建
  5. 先创建父类的对象: 1. 父类对象中的所有基本类型变量都被置为默认值,对象引用被设为 null 2.调用基类的构造器(基本类型和引用类型的显示赋值实际上会被提取到构造器方法中,代码块中的显示赋值语句也会被提取到构造器中)
  6. 创建子类的对象,过程和创建父类的对象相同

总结:

  1. 静态代码块比非静态代码块先执行
  2. 静态变量只会分配一次空间,静态代码块只会执行一次
  3. 代码块中的语句比构造器中的语句先执行(可以看出将代码块中的语句提到构造器中的前面部分)
  4. 变量值的变化: 分配空间和默认值->显示指定的值(如果定义时指定值和代码块中指定值同时存在,按定义的值和代码块的相对位置来判断,最后更新的值为最终的值)->构造器方法中指定的值->普通方法中指定的值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CodePanda@GPF

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

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

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

打赏作者

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

抵扣说明:

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

余额充值