[TOC]

Java中问题的解决是围绕展开的

  • 组合 has-a
  • 继承(extends,super) is-a
  • 代理

protected 继承 与 权限

包,类,子类

package com.test;

/**
 * @Author mubi
 * @Date 2019/2/11 6:53 PM
 */
public class Bowl {
    private int a;

    public Bowl(int _a) {
        a = _a;
    }

    protected void set(int _a){
        this.a = _a;
    }

    @Override
    public String toString() {
        return "Bowl{" +
                "a=" + a +
                '}';
    }
}
package com.test;

/**
 * @Author mubi
 * @Date 2019/2/11 6:54 PM
 */
public class BowlSon extends Bowl{
    int b;

    public BowlSon(int _a, int _b) {
        super(_a);
        this.b = _b;
    }

    public void change(int _a, int _b){
        // 子类方法能够访问基类的set方法,因为set方法在子类中是protected
        set(_a);
        this.b = _b;
    }

    @Override
    public String toString() {
        return "BowlFa{" +
                "b=" + b +
                '}' + super.toString();
    }
}
package com.other;

import com.test.Bowl;
import com.test.BowlSon;

/**
 * @Author mubi
 * @Date 2019/2/11 6:57 PM
 */
public class MainOther {
    public static void main(String[] args) throws Exception {
        Bowl b1 = new Bowl(1);
        BowlSon bowlSon = new BowlSon(1,2);
        bowlSon.change(3,4);
        System.out.println(b1);
        System.out.println(bowlSon);
    }
}

向上转型

如下:Wind继承Instrument,将Wind转换成Instrument引用的动作,称为向上转型; 同理:向下转型

Instrument
    ^
    |
  Wind

继承和组合的选择: 如果需要从新类到基类的向上转型,那么继承是必要的,否则需要考虑用继承还是用组合

final(无法改变的)- 设计或效率

final 数据认识


import java.util.Random;

class Value{
    int i;

    public Value(int i) {
        this.i = i;
    }
}

public class FinalData{
    private static Random rand = new Random(47);
    private String id;

    public FinalData(String id) {
        this.id = id;
    }
    // can be compile-time constants
    private final int valueOne = 9;
    private static final int VALUE_TWO = 99;
    // Typical public constant
    // final 说明是个常量, static 强调只有一份 (编译期常量)
    public static final int VALUE_THREE = 39;
    // can not be compile-time constants
    // 不能因为是final,就认为在编译时可以知道它的值; 在运行时使用随机生产的数值来初始化
    private final int i4 = rand.nextInt(20);
    // 装载时已经初始化了,而不是每次创建一个对象时都初始化
    static final int INT_5 = rand.nextInt(20);
    private Value v1 = new Value(11);
    private final Value v2 = new Value(22);
    private static final Value VAL_3 = new Value(33);
    // Arrays
    private final int[] a = {1,2,3,4,5};

    @Override
    public String toString() {
        return "id:" + id + " i4:" + i4 + " INT_5:" + INT_5;
    }

    public static void main(String[] args) throws Exception {
        FinalData fd1 = new FinalData("fd1");

//        fd1.valueOne++; // error: cannot change value
        fd1.v2.i ++; //Object is not constant
        fd1.v1 = new Value(9); // ok , not final
        for(int i=0;i<fd1.a.length;i++){
            fd1.a[i] ++; // Object is not constant
        }
//        fd1.v2 = new Value(0); //error, can not, 无法将v2再指向其它对象引用,v2是final类型的
//        fd1.VAL_3 = new Value(1); // change reference,error同上
//        fd1.a = new int[3]; // 数组也一样, error同上
        System.out.println(fd1);
        System.out.println("Creating new FinalData");
        FinalData fd2 = new FinalData("fd2");
        System.out.println(fd1);
        System.out.println(fd2);
    }
}
/* output
 id:fd1 i4:15 INT_5:18
 Creating new FinalData
 id:fd1 i4:15 INT_5:18
 id:fd2 i4:13 INT_5:18
 */
  • finalstatic final 的区别

static属于类,不属于实例,静态区域

final 参数

在参数列表中以声明的方式将参数指明为final, 这意味着你无法在方法中更改参数引用所指向的对象

void with(final int a){
    a = 10; // illegal, a is final
}

final 方法

  • final 方法的使用的两个原因

  • 将方法锁定,以防止任何继承类修改它的含义

  • 效率:Java早期实现中,如果将一个方法指明为final, 就是同意编译器将针对该方法的所有调用都转为内嵌调用,以代码副本代替方法调用,可能消除方法调用的开销。如果一个方法很大,则程序代码就会膨胀,可能看不到内嵌带来的任何性能提高,因为,所带来的性能提高会话费于防范诶的时间量而被压缩。(最近的Java版本已经优化此过程)

private 由于无法使用,所以 private 加上 final 修饰词,并没有实际的意义

class WithFinalMethod {
    final void f() {}
}
public class E21_FinalMethod extends WithFinalMethod {
    void f() {} // 报错,final方法无法override
    public static void main(String[] args) {}
}

final 类

不允许继承,不能有子类

初始化及类的加载

  • 加载类的动作仅发生一次

  • 类的第一个实例的创建或者对static成员的访问都有可能引起加载

  • 定义为static的东西,只会被初始化一次

class LoadTest {
    // The static clause is executed
    // upon class loading:
    static {
        System.out.println("Loading LoadTest");
    }
    static void staticMember() {}
}

public class MainTest {
    public static void main(String args[]) {
        System.out.println("Calling static member");
        LoadTest.staticMember();
        System.out.println("Creating an object");
        new LoadTest();
    }
}
/*output

Calling static member
Loading LoadTest
Creating an object
 */

巩固学习:第5章,总结一个对象的创建过程

class LoadTest {
    public LoadTest(){
        System.out.println("LoadTest constructor");
    }
    static {
        System.out.println("Loading LoadTest");
    }
    static void staticMember() {}
}

public class MainTest {
    public static void main(String args[]) {
        System.out.println("Calling static member");
        LoadTest.staticMember();
        System.out.println("Creating an object");
        new LoadTest();
        new LoadTest();
    }
}
/*output

Calling static member
Loading LoadTest
Creating an object
LoadTest constructor
LoadTest constructor
 */

Copyright @doctording all right reserved,powered by Gitbook该文件修改时间: 2020-04-14 11:12:42

results matching ""

    No results matching ""