JAVA基础之复用类

组合语法

在新类中产生现有类的对象

继承语法

按照现有类的类型来创建新类
继承会自动得到基类中所有域和方法
在继承的过程中,并不一定非得使用父类的方法,也可以在子类中添加新方法
对于子类对象来说,除了调用子类的可用方法外,还可以调用父类中所有可用方法
  • 关键字:extends
class B extends A {}
  • 关键字:super
重写的方法中调用对应父类中的方法使用super
  • 初始化基类
当创建了一个导出类的对象时,该对象包含了一个基类的子对象
该子对象与用基类直接创建的对象是一样的
在导出类构造器中调用基类构造器来进行初始化
JAVA会自动在导出类的构造器中插入对基类构造器的调用
  • 基类构造器
1,总是被调用
2,在导出类构造器之前被调用
  • 带参数的构造器
没有默认的基类构造器,或想调用带参数的基类构造器,就必须用关键字super显式的  编写调用基类构造器的语句,并配以适当的参数列表
调用基类构造器必须是在导出类构造器中要做的第一件事
class Base {
    public Base(int num) {}
}

class Child extends Base {
    public Child() {
        super(1);
    }
}

代理

我们使用代理时,可以拥有更多的控制力,因为我们可以选择只提供在成员对象中的方法的某个子集
// PackageManager 就是 PackageManagerService的代理
// 该例子使用了组合和继承
class PackageManagerService {
    public void installPackage() {/* ... */}
    public void deletePackage() {/* ... */}
    protected void getPackageInfo() {/* ... */};
}

abstract class PackageManager {
    public abstract void installPackage();
    public abstract void deletePackage();
}

class ApplicationPackageManager extends PackageManager {
    PackageManagerService mPm;

    public ApplicationPackageManager() {
        mPm = new PackageManagerService();
    }

    @Override
    public void installPackage() {
        mPm.installPackage();
    }

    @Override
    public void deletePackage() {
        mPm.deletePackage();
    }
}

结合使用组合和继承

  • 名称屏蔽
扩展类可以使用与基类完全相同的特征签名及返回类型来覆盖具有相同名称的方法
@Override可以防止不想重载时意外进行了重载
class Base {
    void print(int i) {}
    void print(String s) {}
}

class Child extends Base {
    void print(Double d) {}

    @Override
    void print(int i) {/* .. */ }
}

在组合和继承之间选择

组合和继承都允许在新的类中放置子对象,组合是显式地这么做,继承是隐式地做
  • 区别
组合:通常用于想在新类中使用现有类的功能而非它的接口,即在新类中嵌入某个对象,让其实现所需的功能。(has-a/有一个)的关系
继承:使用某个现有类,并开发一个它的特殊版本。(is-a/是一个)的关系。如果需要向上转型,那么继承是必须的

protected关键字

就类用户而言,这是private的,但对于任何继承于此类的导出类或其他任何位于同一包内的类来说,它却是可访问的
protected也提供了包访问权限
尽管可以创建protected域,但是最好的方法还是将域保持为private,然后通过protected方法来控制类的继承者的访问权限

向上转型

能够向基类发送的所有信息同样也可以向导出类发送
向上转型是从一个较专用类型向较通用类型转换,所以总是很安全的
class Instrument {
    protected void play() {
        System.out.print("Instrument play");
    }

    public static void tune(Instrument instrument) {
        instrument.play();
    }
}

public class Test extends Instrument {
    @Override
    protected void play() {
        System.out.print("Test play");
    }

    public static void main(String[] args) {
        Instrument.tune(new Test());
    }
}
//输出Test play

final关键字

  • final数据
1,一个永不改变的编译时常量
2,一个在运行时被初始化的值,而不希望它被改变
一个既是static又是final的域只占据一段不能改变的存储空间
对于基本类型,final使数值恒定不便
对于对象引用,final使引用恒定不便,然而对象其自身却是可以被修改的
  • 空白final
被声明为final但又未给定初值的域
class Value {
    int v;

    public Value(int i) {
        v = i;
    }
}

public class Test {
    public static final int NUM = new Random().nextInt(10); // 编译时常量
    final int num = new Random().nextInt(10); // 运行时常量,编译时并不知道值
    static final Value mValue = new Value(1); // 对象引用不能改变,但对象自身可改变
    final int t; // 空白final

    public Test() {
        t = 1;
    }

    Test(int i) {
        t = i;
    }

    public static void main(String[] args) {
        System.out.println(NUM + " " + new Test().num + " " + mValue.v + " " + new Test(1).t);
        mValue.v = 2;
        System.out.println(NUM + " " + new Test().num + " " + mValue.v + " " + new Test(2).t);
        // NUM始终不变
    }
}
  • final参数
将参数声明为final,意味着无法在方法中更改参数引用所指向的对象
主要用来向匿名内部类传递数据
class Value {
    int v = 10;
}

public class Test {
    void print(final int i) {
        //i++; 不可修改,只能使用
        System.out.println(i + 1);
    }

    void print(final Value value) {
        //value = new Value(); 不可修改,只能使用
        System.out.println(value.v);
    }

    public static void main(String[] args) {
        new Test().print(1);
        new Test().print(new Value());
    }
}
  • final方法
final方法不能被重写,用于方法锁定,以防止任何继承类修改它的含义
作用:确保在继承中使方法行为保持不变,并且不被覆盖
  • final和private关键字
类中所有的private方法都隐式地指定为final的
由于无法取用private方法,所有也就无法覆盖它
"覆盖"只有在某方法是基类的接口的一部分时才会出现,如果方法为private,它就不是接口的一部分
  • final类
final类不能被继承
final类中所有的方法都隐式指定为final的

初始化及类的加载

类的代码在初始使用时才加载(创建类的第一个对象或访问static域或static方法)
static的东西只会被初始化一次
  • 继承与初始化
1,加载基类->加载导出类
2,基类static初始化,static域->static代码块
3,导出类static初始化,static域->static代码块
4,设置所有基本类型为默认值,对象引用被设置为null
5,基类构造器被调用,显式赋值->构造代码块->构造函数
6,导出类构造器被调用,显式赋值->构造代码块->构造函数
class Base {
    int i1 = getI1();
    static int i2 = getI2();
    int i3;
    static int i4;
    int i5;

    int getI1() {
        System.out.print("i1 ");
        return 1;
    }

    static int getI2() {
        System.out.print("i2 ");
        return 2;
    }

    static {
        i4 = 4;
        System.out.print("i4 ");
    }

    {
        i3 = 3;
        System.out.print("i3 ");
    }

    public Base() {
        i5 = 5;
        System.out.print("i5 ");
    }
}

public class Test extends Base {
    int j1 = getJ1();
    static int j2 = getJ2();
    int j3;
    static int j4;
    int j5;

    int getJ1() {
        System.out.print("j1 ");
        return 1;
    }

    static int getJ2() {
        System.out.print("j2 ");
        return 2;
    }

    static {
        j4 = 4;
        System.out.print("j4 ");
    }

    {
        j3 = 3;
        System.out.print("j3 ");
    }

    public Test() {
        j5 = 5;
        System.out.print("j5 ");
    }

    public static void main(String[] args) {
        System.out.print("main ");
        new Test();
    }
}
//输出为:i2 i4 j2 j4 main i1 i3 i5 j1 j3 j5 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值