• Java基础笔记(十六)——继承


    继承

    提取出一些共性特征,作为父类,子类就可以继承父类的这些开放成员,子类再添加自己独有的属性和方法。如果再有类具有这些共同特征,也可继承这个父类。

    特点:1.利于代码复用     2.缩短开发周期

    继承是一种类与类之间的关系。

    使用已存在的类的定义作为基础建立新类。

    子类(派生类)——|>父类(基类)

    新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类的特征(即继承全部开放特征)。

    满足“A is a B”的逻辑关系。如:猫和狗都继承动物类,学生和老师都继承人类。

    继承的实现(extends)

    父类

    class Animal{

      //公共的属性和方法

    }

    子类,只能继承一个父类

    class Dog extends Animal{

          //子类特有的属性和方法

    }

    class Cat extends Animal{

    }

    子类可以访问父类非私有成员【把父类的非私有(private修饰但提供了getter/setter方法不是私有)成员(属性和方法)当自己的用】。

    父类不可以访问子类特有成员(即时public也不行)。

    方法重写&方法重载

    先回顾一下方法重载

    1.同一个类中

    2.方法名相同,参数列表不同(参数顺序、个数、类型),与参数名无关。

    3.与方法返回值类型,访问修饰符无关。

    方法重写:子类也具有父类的方法,但实现的功能有所不同,需要重写。即与父类同名的方法。

    1.有继承关系的子类中。

    2.子类重写父类的方法。

    3.返回值类型,方法名,参数列表(参数类型、顺序、个数)都有与父类继承的方法相同,与方法的参数名无关(参数名相同与否均可)。

    注:返回值类型,可以是子类类型。父类方法的返回值是父类类型,子类重写方法时,其返回值类型既可以是父类类型,也可以是子类类型,但只能向下兼容,不能向上兼容,不能是Object类

    如:父类  public Animal create(){ return new Animal();}

    子类   @Override  

              public Dog create(){ return new Dog();}

    4.子类方法的访问修饰符的访问范围需要大于等于父类的访问范围。private<default<protected<public

    当子类重写父类方法后,子类对象调用的是重写后的方法,子类定义与父类同名的方法,要重写;子类可以定义与父类重名的属性。

    super:父类对象的引用

    子类可以把父类的开放成员(属性和方法)当作自己的用,子类包括继承父类的方法和自己重写父类的的方法。在子类的方法中,调用其它其它成员方法,在包含父类方法以及重写父类的方法情况下,子类肯定是调用重写的方法,那么如果想要调用父类的方法,而不是重写的那个方法,可以用super关键字来调用。如:super.eat();    super.setAge(3);      父类的属性可以用super调用,或者子类直接用就行。假如父类有name属性,子类不再定义了,如果成员方法或构造方法中用name属性,可以直接用或者super.name。

    当然了,如果父类的方法没有被重写,子类对象和子类方法中在调用父类方法时如同自己的一样,子类在调用父类的开放属性时也是同自己定义的一样去使用。

    父类的构造方法不允许被继承,也就不允许被重写了。

    在有继承关系的程序初始化顺序:

    在Java中,当实例化对象时,对象所在类的所有成员变量首先要进行初始化,只有当所有类成员完成初始化后,才会调用对象所在类的构造函数创建对象。

    父类静态成员——>子类静态成员——>父类对象构造——>子类对象构造

    静态成员【静态变量(也就是static成员属性)和静态代码块】,其中访问修饰符不影响成员加载顺序,谁先谁后与书写位置有关。

    假设静态变量在静态代码块前面:(如果出现位置相反,就反过来)

    父类静态变量、父类静态代码块、子类静态变量、子类静态代码块、父类非静态变量(成员属性)、父类构造代码块、父类构造函数、子类非静态变量、子类构造代码块、子类构造函数。

    (1)静态优先非静态,静态属于类加载,只初始化一次,非静态属于对象,随着对象的创建可能会初始化多次。

    (2)父类优先于子类进行初始化。Object类是超类(顶级父类。

    (3)成员变量按出现顺序进行初始化,即使在方法中,也在任何方法被调用前(包括构造方法)先初始化。

    构造方法的调用必须放在构造方法里,子类构造(包括带参构造)默认调用父类无参构造方法,如果要调用父类带参构造,可以通过super(参)调用父类允许被访问的其它构造方法。super必须在子类构造方法中的第一行。如:super(name,month);

    super小结:

    代表父类引用。

    -访问父类成员方法   super.print();

    -访问父类属性          super.name;

    -访问父类构造方法   super();

    (1)子类的构造的过程中必须调用其父类的构造方法(一层一层往上找,直到Object类)。

    (2)如果子类的构造方法中没写super,则系统默认调用父类的无参构造方法,没显式写无参构造的,系统默认提供。

    (3)如果父类中写了带参构造却没写无参构造,在子类的构造方法中,又没写super(参),则编译出错。【因为父类写带参构造了,系统就不会再提供无参构造了,而子类不写super(参),就会默认去调用父类的无参构造去,找不到,就出错。】如果父类既写了无参构造又写了带参构造,子类的构造方法中不写super,默认调用父类无参构造,写了super();也是调用无参构造,写了super(参),调用带参构造。其中子类的构造方法包括带参构造和无参构造都符合上述说法,创建对象时调用哪个构造,哪个构造都要遵守上述规则。super();就是调用父类无参构造,可写可不写,super(参)是调用指定的父类的带参构造。

    (4)使用super();   super(参);   必须放在子类构造方法中的第一行。

    super&this

    在构造方法(有参构造)中写this(); 是先调用同类中的无参构造,this();也必须写在第一行。所以构造方法间调用时,this与super不能共存。

    this:当前类对象的引用

    -访问当前类的成员方法

    -访问当前类的成员属性

    -访问当前类的构造方法

    -不能在静态方法中使用

    super:父类对象的引用

    -访问父类的成员方法

    -访问父类的成员属性

    -访问父类的构造方法

    -不能在静态方法中使用

    Object类

    -Object类是所有类的父类。

    -一个类没有使用extends关键字明确表示继承关系,则默认继承Object类(包括数组)。

    -Java中的每个类都可以使用Object中定义的方法。【Object类是java.lang包里的(String、System...),此包系统默认加载,不要手动import】

    -Object类中的equals方法和"=="是一样的,看地址是否相同,即是否指向同一个对象。String类中重写了Object类中的equals方法,比较对象的内容是否相同。

    public class TestOne {
        public static void main(String[] args){
            Animal one=new Animal("小one",2);
            Animal two=new Animal("小one",2);
            //equals测试:继承Object类中的equals方法时,比较的是两个引用是否指向同一个对象。
            boolean flag=one.equals(two);
            System.out.println("one和two的引用比较:"+flag);
            System.out.println("one和two的引用比较:"+(one==two));
            System.out.println("==============================");
            //String类重写了Object类的equals方法,比较的是对象的内容是否相同
            String str1=new String("hello");
            String str2=new String("hello");
            flag=str1.equals(str2);
            System.out.println("str1和str2的引用比较:"+flag);
            System.out.println("str1和str2的引用比较:"+(str1==str2));
        }
    }
    
    //运行结果
    小one2岁
    小one2岁
    one和two的引用比较:false
    one和two的引用比较:false
    ==============================
    str1和str2的引用比较:true
    str1和str2的引用比较:false

    那如何比较两个对象的内容值?

    需要重写Object类中的equals方法

    在Animal类中重写equals方法,使得比较对象的内容

    public boolean equals(Object obj){
            if(obj==null)   //如果传入的对象为空,防止出现NullPointerException
                return false;
            Animal temp=(Animal)obj; //把传入的对象obj强转成Animal类型
            if(this.getName().equals(temp.getName())&&this.getAge()==temp.getAge()){
                return true;
            }
            else
                return false;
        }
    
    //运行结果
    one和two的引用比较:true
    one和two的引用比较:false
    ==============================
    str1和str2的引用比较:true
    str1和str2的引用比较:false

    在Animal类中重载equals方法,使得比较对象的内容,不用类型强制转换,直接传入Animal类型

    public boolean equals(Animal animal){
            if(animal==null)
                return false;
            if(this.getName().equals(animal.getName())&&this.getAge()==animal.getAge()){
                return true;
            }
            else
                return false;
        }
    
    //运行结果
    one和two的引用比较:true
    one和two的引用比较:false
    ==============================
    str1和str2的引用比较:true
    str1和str2的引用比较:false

    如果重写和重载这两段代码都放在Animal类中,主函数中对象调用的是后者,因为后者通过Animal类型参数重载了equals方法,对象调用时会自动定位类型匹配方法。

    Object类中的toString方法

    返回这个类的字符串表现形式:类名+@+地址哈希值

    (1)输出对象名时,默认会直接调用类中的toString

    (2)继承Object中的toString方法时,输出对象的字符串表现形式:类型信息+@+地址信息

    (3)子类可以通过重写toString方法的形式,改变输出的内容以及表现形式

    在测试类中

    public class TestOne {
        public static void main(String[] args){
            Animal one=new Animal("小one",2);
            System.out.println(one.toString());
            System.out.println(one);
        }
    }
    
    //运行结果
    Animal@26cbb7db
    Animal@26cbb7db

    在Animal类中重写toString方法

    public class Animal {
    
        private String name;
        private int age;
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public Animal(String name,int age){
            this.name=name;
            this.age=age;
            System.out.println(name+age+"岁");
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String toString(){   //重写toString方法
            return "昵称:"+this.getName()+";年龄:"+this.getAge();
        }
    }
    
    //运行结果
    小one2岁
    昵称:小one;年龄:2
    昵称:小one;年龄:2
  • 相关阅读:
    排序:归并排序
    错误编码 = 10022 错误消息 = SDK 组件 Qupaisdk 启动出错,错误消息为 [Qupaisdk], the android stack error message is Fail to start the plugin, which is caused by No implem
    关于百川趣拍64位的问题
    在 APK 中找不到对应的 securityguard***.so 文件或者 so 文件载入出错
    趣拍proguard配置
    android多国语言文件夹
    错误编码 = 17
    阿里百川趣拍接入指南
    Conversion to Dalvik format failed:Unable toexecute dex: method ID not in [0, 0xffff]: 65536
    Conversion to Dalvik format failed:Unable toexecute dex: method ID not in [0, 0xffff]: 65536
  • 原文地址:https://www.cnblogs.com/tendo/p/10501069.html
Copyright © 2020-2023  润新知