Java基础 -----继承性、多态性、包装类、super、Object

1、面向对象的特征之二: 继承性

1.1、继承性的概述

为什么要有继承性?

多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。

继承性的好处

  1. 减少了代码的冗余,提高了代码的复用性
  2. 便于功能的拓展
  3. 为多态性提供了前提

1.2、继承性的格式与规定

继承性的格式

class  A  extends B
A  :  子类、派生类、 subclass
B  :  父类、超类、基类、superclass
  • 子类(A)继承了父类(B),子类就获得了父类声明的所有属性和方法(private修饰的属性和方法除外,因为受到封装性的影响,使得子类不能直接调用父类的结构)(继承性的体现)
  • 子类继承父类以后,还可以声明自己特有的属性或方法,实现功能的拓展。

在这里插入图片描述

继承性的规定

  1. 一个类可以被多个子类继承
  2. 一个类只能有一个父类(单继承性)
  3. 子类继承父类后,就获取了直接父类以及所有间接父类中声明的属性和方法。
  4. 父类、子类是相对的(直接父类、间接父类)
  5. 如果我们没有显式的声明一个类的父类的话,则此类继承于 java.lang.Object 类
  6. 所有Java类直接或间接继承java.lang.object类(意味着,所有的 java 类具有 java.lang.Object 类声明的功能)

1.3、方法的重写

  • 创建子类对象以后,通过子类对象调用与父类同名同参的方法时,子类覆盖父类的方法(子类的权限修饰符范围不小于父类的)

重写的规定:

  1. 重写无法覆盖属性
  2. 只能覆盖同名同参的方法
  3. 子类不能重写private修饰的方法,计算机会自动任务是两个不同的方法
  4. 子类抛出的异常类型不大于父类
  5. 关于返回值类型
父类子类
voidvoid
基本数据类型相同的基本数据类型
引用数据类型(A)A类或A的子类

重写与重载的区别!!!

  • 方法的重写和重载是Java多态性的不同表现。
  • 重写是子父类之间多态性的一种表现,重载是一个类中多态性的一种表现。
  • 如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载
  • 如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写,当子类对象调用此方法时,那么父类中同名同参的方法相当于被“屏蔽”了

2、super关键字

  • super(父类的)
  • super可以用来调用:属性、方法、构造器

super的使用

  • 我们可以在子类的方法或构造器中,通过 " super.属性 “或” super.方法 “的方式,显式的调用父类中声明的属性或方法。但是,通常情况下,我们习惯去省略这个"super.”
  • 当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的使用"super.属性"的方式,表明调用的是父类中声明的属性。
  • 子类重写了父类中的方法后,我们想在子类的方法中调用父类中被重写的方法时,必须显式的使用"super.方法"的方式,表明调用的是父类中被重写的方法。
  • super调用构造器
    • 我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
    • "super(形参列表)"的使用,必须声明在子类构造器的首行!
    • 我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二选一,不能同时出现。
    • 在类的多个构造器中,至少有一个类的构造器使用了"super(形参列表)",调用父类中的构造器。
    • 在构造器的首行,既没有显式的声明"this(形参列表)“或"super(形参列表)”,则默认的调用的是父类 中的空参构造器。super()

3、面向对象的特征之三: 多态性

多态性的理解:可以理解成一种事物的多种态性
对象的多态性:子类的对象赋给父类的引用(父类的引用指向子类的对象)

3.1、多态的使用

  • 在编译期,只能调用父类声明的方法
  • 在执行期,执行子类重写父类的方法(运行时行为)
    • 简称:编译时,看左边;运行时,看右边。
  • 若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)
  • 使用前提:
    • 1、类的继承关系
    • 2、方法的重写
  • 对象的多态性:只适用于方法,不适用于属性
  • 有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类的属性和方法不能调用。
  • 动态绑定:编译时调用父类方法,运行时执行重写子类方法的过程
  • 虚拟方法:多态情况下,父类的方法称为虚拟方法
public class PersonTest {
	public static void main(String[] args) {

		Person p1 = new Person();
		p1.eat();

		Man man = new Man();
		man.eat();
		man.age = 25;
		man.earnMoney();
		
		// 对象的多态性,父类的引用指向子类的对象
		Person p2 = new Man();
		
		// 多态的使用:当调用子父类同名同参数方法时,实际调用的是子类重写父类的方法---虚拟方法调用
		p2.eat();
		p2.walk();

	
		// 不能调用子类(Man类)所特有的方法、属性,编译时,p2是Person类型,而earnMoney()属于Man类
		// p2.earnMoney();

3.2、instanceof关键字

  • a instanceof A:判断对象a是否是类A的实例。如果,返回true,如果不是,返回false;
  • 使用情境:
    • 为了避免在向下转型时出现ClassCastException异常,我们在进行向下转型之前,先进行
      instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。
  • 当A是B的子类时,如果 a instanceof A == true ,那么 a instanceof B == true

在这里插入图片描述

// 如何才能调用子类所特有的属性和方法?
		// 使用强制类型转换符,也可称为:向下转型
		Man m1 = (Man) p2;
		m1.earnMoney();
		m1.isSmoking = true;

		// 使用强转时,可能出现ClassCastException异常
		// Woman w1 = (Woman)p2;
		// w1.goShopping();
       
       //使用instanceof关键字避免异常的出现
       if( p2 instanceof woman)
          woman w1=(woman)p2
        //不过显然这个是无法转换的,因为虽然man类与woman类都继承与person类,但是这两个类之间是并列关系无法实现类型转换

3.3、多态是运行时行为的证明

证明如下:

public class test {

    public static aniamls choose(int key){
        switch (key){
            case 1:
                return new lion();

            case 2:
                return new monkey();

            case 3:
                return new cattle();

        }

        return new aniamls();
    }

    public static void  main(String[] args){
        int key=(int)( Math.random()*3 +1);
        System.out.println(key);

        choose(key).eat();

    }
}

class aniamls{
    public void eat(){
        System.out.println("动物吃东西");
    }
}

class lion extends aniamls{
    public void eat(){
        System.out.println("狮子吃肉");
    }
}

class monkey extends aniamls{
    public void eat(){
        System.out.println("猴子吃香蕉");
    }
}

class cattle extends aniamls{
    public void eat(){
        System.out.println("牛吃草");
    }
}
  • 你无法在编译期间就知道程序会调用哪一个对象,只有在运行期间才能知道。

4、Object类

  • 全名 java.lang.Object 类
  • Object类是所有Java类的根父类
  • 如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类
  • Object类中的功能(属性、方法)就具有通用性。
  • Object中无属性
  • Object类中常用方法
    在这里插入图片描述

5、 “ == ” 与 equals ()的对比

  • ==
    • 可以使用在基本数据类型变量和引用数据类型变量中
    • 如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。
    • 如果比较的是引用数据类型变量:比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
    • == 使用时,必须保证符号左右两边的变量类型一致。
  • equals()
    • 是一个方法,而非运算符
    • 只能适用于引用数据类型。
    • equals()的源码
public boolean equals(Object obj){
 		return (this == obj);
 		}
 //由此可以知道,equals()与  ==  作用是相同的
 //一般情况下,如果我们需要调用equals() 都会在目标类中重写它,使其充当比较对象实体的功能
 
 //重写的方法
  public boolean equals(Object o) {
        if (this == o) 
          return true;
        if (o instanceof Person){
             Person p1=(Person)o;
             if(this.name == p1.name)  //比较Person类中name属性的实体
                return true;
        }else
           return false;
    }
//在编译中,我们一般直接调用idea写好的结构(快捷键 Alt + Ins)

6、包装类

6.1、包装类的使用

基本数据类型对应包装类
byteByte
shortShort
intInteger
longLong
douubleDouble
floatFloat
booleanBoolean
charCharacter

6.2、包装类与基本数据类型的转换

在这里插入图片描述

package test1;

import org.testng.annotations.Test;

public class WrapperTest {
    @Test
    public void test1() {
        //基本数据类型  ——》 包装类

        //方式1:调用包装类构造器
        Integer t1 = new Integer(15);
        System.out.println(t1);
        String t2 = new String("ABC");
        System.out.println(t2);

        //特殊的: 对于纯数字的字符串 也可以调用 整型 包装类的构造器
        Integer t3 = new Integer("123");
        System.out.println(t3);
        Double t4 = new Double("123.456");
        System.out.println(t4);


        //方式2:自动装箱
        Integer t5 = 100;
        System.out.println(t5);
        Double t6 = 123.4;
        System.out.println(t6);

    }

    @Test
    public void test2() {
        //包装类-》基本数据类型

        //方式1:调用 XXXValue()
        Integer t1 = new Integer(15);
        int t2 = t1.intValue();
        System.out.println(t2);

        //使用了匿名对象
        float t3 = new Float(454.58).floatValue();
        System.out.println(t3);


        //方式2:自动拆箱
        int t4 = new Integer(20);
        System.out.println(t4);

    }


    @Test
    public void test3() {
        //基本数据包类型、包装类 -》 String类型

        //方式1: + “ ”

       String t1=15+"";
       System.out.println(t1);

       //方式2: 调用String类中的valueOf(XXX)方法
        String t2=String.valueOf('a');
        System.out.println(t2);

        //方式3: 调用包装类的toString()方法
        String t3= new Integer(11).toString();
        System.out.println(t3);


    }


    @Test
    public void test4(){
        //String类型 -》 基本数据类型、包装类

        //方式1:调用各个包装类的 parseXXX()方法

        Integer t1=Integer.parseInt("123");
        System.out.println(t1);

        //方式2:调用构造器
        Integer t2=new Integer("789");
        System.out.println(t2);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值