Java——继承、重写与多态

一、继承

1、什么是继承

继承是一种特性,利用继承可以重用现有类生成新类,也是代码重用的一种体现。

  • 通过关键字extends继承一个已有的类

  • 父类:被继承的类(超类、基类)

  • 子类:新的类(派生类)

  • Java继承的特点:单继承,只有一个直接父类

  • 继承可以持续进行,形成复杂的继承层级结构

  • 如果一个类的声明中没有使用关键字extends,那么这个类被系统默认为是继承了Object父类

2、继承的作用

  • 简化了人们对事物的认识和描述,能清晰体现相关类间的层次结构关系

  • 提供软件复用功能

  • 通过增强一致性来减少模块间的接口和界面,大大增加程序的易维护性。

3、继承特性

父类中的:

  • public:将被子类继承、直接使用;

  • private:将被隐藏,在子类中无法访问

  • protected:同一包下可以访问,不同包下子类可以访问

  • default:同一包下可以使用,不同包下对子类也隐藏

二、重写

1、什么叫重写

方法重写是指,子类中定义了一个方法,并且这个方法的名字、返回类型、参数类型及参数的个数与父类所继承的方法完全相同。

2、重写的目的及作用

子类可以通过方法重写来隐藏父类的方法,又称为“覆盖”。

  • 通过方法重写,子类可以把父类的状态和行为变成自己的状态和行为

  • 只要父类的方法能够被子类继承,子类就能重写这个方法

  • 一旦子类重写了这个方法,就表示隐藏了所继承的这个方法

  • 如果通过子类对象调用这个方法,那也是调用重写后的方法

3、多态性

调用同一名称的方法,能实现不同需求下的功能

  • 重载——发生在同一类中多态

  • 重写——发生在子类中

三、super关键字

1、应用场景及作用

  • super的使用场合用来访问直接父类隐藏的数据成员,其使用形式如下:

    super.数据成员
  • 用来调用直接父类中被覆盖的成员方法,其使用形式如下:

    super.成员方法(参数)
  • 用来调用直接父类的构造方法,其使用形式如下:

    super(参数)
    super()

四、向上转型

1、向上转型

向上转型——父类的引用变量可以指向子类的对象 如:

Employee emp = new Salesman(...);

2、特性

引用变量emp由于是按照Employee类型声明的,因此:

  • 只能调用父类的成员方法或公共属性

  • Salesman类型特有的方法和属性则不能使用

  • 子类重写父类方法,调用的是重写后的方法

3、示例

public class Test{
    public static void main(String[] args){
        Employee emp = new SalesMan();
        emp.working();
        emp.salesShow();    //报错,子类特有方法不能调用
        emp.eat();          //eat()没有被重写,输出 emp eating...
    }
}
//输出 salesman working

五、Object类

1、简介

Object类是所有类的超类,也就是说,Java中的每一个类都是由Object类扩展而来的。因而每当你创建一个对象,它都将拥有Object类中的全部方法。

2、常用方法

方法用途
Object clone()创建与该对象的类相同的新对象。
boolean equals(Object)比较两对象是否相等。
void finalize()当垃圾回收器确定不存在对该对象的引用时,垃圾回收器在对该对象执行垃圾回收前调用该方法。
class getClass()返回一个对象的运行时类型信息。
int hashCode()返回该对象的散列码值。
void notify()激活等待在该对象的监视器上的一个线程。
void notifyAll()激活等待在该对象的监视器上的全部线程。
String toString()返回该对象的字符串表示。
void wait()等待这个对象另一个更改线程的通知。
void wait(long)等待这个对象另一个更改线程的通知。
void wait(long, int)等待这个对象另一个更改线程的通知。

3、instanceof说明(了解)

instanceof是一个Java关键字,用于检查一个对象是否是一个类的实例或是其子类的实例。它的语法是 对象 instanceof 类名,返回一个布尔值。

4、final

  • 修饰属性是常量,只能被赋值一次

  • 修饰的方法不能被重写

  • 修饰类不能被继承

六、字符串补充

1、字符串常用比较方法

1.1、常用的字符串比较成员方法有:
  • equals()

  • equalsIgnoreCase()

equalsIgnoreCaseequals方法的功能类似,不同之处是不区分字母的大小写

1.2、equals方法和==的区别
String string1 = "aaa";
String string2 = "aaa";
String string3 = new String("aaa");
String string4 = new String("aaa");
string1 == string2;         //true
string1.equals(string2);    //true
string3 == string4;         //false
string3.equals(string4);    //true

首先,string1 = "aaa";string2 = "aaa";都指向常量池的同一个对象aaa;其调用==和string1.equals(string2)方法其效果是一样的

String string3 = new String("aaa");String string4 = new String("aaa");是在heap堆中创建两个新对象,他们引用的地址是不同的,从而使得==出现不相等的情况。

string3.equals(string4)所引用的对象是同一类对象且属性内容相等(并不一定是相同对象)时返回true, 就出现了上面的结果

String类重写了Object中的equals()方法,源码如下

public boolean equals(Object anObject) {
        if (this == anObject) {     //判断是否指向同一地址
            return true;
        }
        if (anObject instanceof String) {               //判断是否为String类型
            String anotherString = (String)anObject;
            int n = value.length;                   //String底层存的是final char[]
            if (n == anotherString.value.length) {  //遍历数组
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {                  //逐个值比较
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

1.3、常量池(了解)

Class文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到常量池中。

Java中基本类型的包装类的大部分都实现了常量池技术,即Byte,Short,Integer,Long,Character,Boolean。这6种包装类默认创建了数值[-128,127]的相应类型的缓存数据,但是超出此范围仍然会去创建新的对象。 两种浮点数类型的包装类Float,Double并没有实现常量池技术

字符串池是Java为了重用String对象而设置的一个缓存池,字符串池的实现有一个前提条件:String对象是不可变的。因为这样可以保证多个引用可以同时指向字符串池中的同一个对象。如果字符串是可变的,那么一个引用操作改变了对象的值,对其他引用会有影响,这样显然是不合理的

其中需要注意的是:

  • 5大基础类型包装类范围只有[-128,127]

    Integer i = 127;
    Integer j = 127;
    i == j;         //true
    Integer x = 128;
    Integer y = 128;
    x == y;         //false
  • string是不可变的,所以有一个常量缓存池,这也是上面在字符串中==equals有特殊情况的原因

2、StringBuffer类、StringBuilder

由于字符串的底层存储是final char[]型存储,在赋初值以后就是不可变的。如果在项目中需要频繁变动字符串内容,就什么多次开辟新的存储空间,然后重新将变量指向新空间,极度浪费运算资源。

在这种场合下,可以使用StringBuilderStringBuffer来节省资源,且这种类中提供大量便捷操作方法。其底层存储逻辑为char[],并未用final修饰,所以这两个类在变化时就无需频繁执行开空间操作。

二者的区别在于:

  • StringBuilder 并未考虑线程安全问题,虽然速度较快,但不推荐在多线程状况下使用

  • StringBuffer 虽然速度较慢,却是线程安全的

2.1、构造方法
构造方法说明
StringBuffer()构造一个没有字符的字符串缓冲区,初始容量为16个字符
StringBuffer(CharSequence seq)构造一个包含与指定的相同字符的字符串缓冲区 CharSequence
StringBuffer(int capacity)构造一个没有字符的字符串缓冲区和指定的初始容量。
StringBuffer(String str)构造一个初始化为指定字符串内容的字符串缓冲区。
2.2、常用方法
方法说明
append(String str)将指定的字符串附加到此字符序列。
capacity()返回当前容量。
deleteCharAt(int index)删除 char在这个序列中的指定位置。
insert(int offset, char c)在此序列中插入 char参数的字符串表示形式。
2.3、示例
package com.woniu.Zhang;
​
public class BuilderApp {
    
    public static void main(String[] args) {
        StringBuilder s1 = new StringBuilder();
        StringBuilder s2 = new StringBuilder(11);
        StringBuilder s3 = new StringBuilder("hello");
        
        System.out.println(s1.length());
        System.out.println(s1.capacity());
        
        System.out.println(s2.length());
        System.out.println(s2.capacity());
        
        System.out.println(s3.length());
        System.out.println(s3.capacity());
        
        System.out.println("--------------------------");
        
        s3.append("world");
        System.out.println(s3.length());
        System.out.println(s3.capacity());
        
        System.out.println("-----------------------------");
        
        s3.append("123456789123");
        System.out.println(s3.length());
        System.out.println(s3.capacity());
    }
​
}
输出:
0
16      //默认开辟长度为16的空间容量
0
11      //可手动设置长度
5
21      //new时新增的字符串,容量为新字符串长度+16
--------------------------
10
21      //未超出当前空间容量,容量不变
-----------------------------
22
44      //超出现有空间长度,直接开辟空间新长度*2
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值