Java-继承、super关键字、重写、抽象、final用法、对象的比较、Object类

26 篇文章 0 订阅

继承

类是对对象的抽象,继承是对某一批类的抽象,从而实现对现实世界更好的建模。
提高代码的复用性!
extands的意思是“扩展”。子类是父类的扩展
不同的叫法:超类、父类、基类、子类、派生类
如何使用继承:
①编写父类 ②编写子类,继承父类

不能被继承的父类成员:
①不能直接访问private成员
②子类与父类不在同包, 使用默认访问权限的成员
③构造方法

多重继承关系的初始化顺序:父类属性->父类构造方法->子类属性->子类构造方法

小结:
– 通过继承可以简化类的定义,实现代码的重用
– 子类继承父类的成员变量和成员方法,但不继承父类的构造方法
– java中只有单继承 ,没有像c++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难于维护。就像我们现实中,如果你有多个父母亲, 那是一个多么混乱的世界啊。多继承,就是为了实现代码的复用性,却引入 了复杂性,使得系统类之间的关系混乱。
– java中的多继承,可以通过接口来实现
– 如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object

package com.petrel.extend;

public class Pet {
    String name;
    int age;
    String tender;

    public Pet(){

    }

    public Pet(String name,int age,String tender){
        this.name = name;
        this.age = age;
        this.tender = tender;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setTender(String tender) {
        this.tender = tender;
    }

    public String getTender() {
        return tender;
    }

    public void play(){
        System.out.println("Pet中的玩");
    }

    @Override
    //toString的用法 如果这里没有这个代码,运行结果是:com.petrel.extend.Pet@4554617c
    public  String toString(){
        return "my name is "+this.name+" . my age is "+this.age+" . my gender is "+this.tender;
    }
}

------------
package com.petrel.extend;

public class dog extends Pet {

    private String color;

    public dog(){

    }

    public dog(String color,String name,int age,String tender){
        //当super在构造方法中使用的话,会默认调用父类的构造方法 注意的点:super一定要放在第一行
        super(name,age,tender);
        this.color = color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getColor(){
        return color;
    }

    @Override
    public void play(){
        //super.play();
        System.out.println("dog中的玩");
    }
    
    @Override
    //父类的值不能满足子类的需要 就只能自己改写
    public String toString() {
        return super.toString()+" . my Color is "+this.color;
    }
}

------------
package com.petrel.extend;

public class penguin extends Pet{

    private String size;

    public penguin(){

    }

    public penguin(String size,String name,int age,String tender){
        super(name,age,tender);
        this.size = size;
    }

    public void setSize(String size){
        this.size = size;
    }

    public String getSize(){
        return size;
    }
}

------------
/**
 * 继承:
 * extands扩展,子类是父类的扩展
 * 1.java中是单继承,不可以有多个父类,不然无法觉得该继承谁
 * 2.父类:超类
 *   子类:基类、派生类
 * 3.父类中的属性和方法都可以在子类中进行(前提是非私有属性和非私有方法)
 *
 *    总结:
 *         1.在创建子类对象的时候一定会优先创建父类对象
 *         2.所有的java类都具备同一个老祖宗类,称之为Object,是所有类的根类
 *
 */

package com.petrel.extend;

public class PetTest {
//String color,String name,int age,String tender
    public static void main(String[] args) {
        dog a = new dog();
        a.setColor("白色");
        a.setName("皮皮");
        a.setAge(12);
        a.setTender("雌");

        penguin b = new penguin();
        b.setName("小企鹅");
        b.setSize("小");

        System.out.println("狗狗的名字:"+a.getName()+"  年龄:"+a.getAge()+"  性别:"+a.getTender()+"  颜色:"+a.getColor());
        System.out.println("企鹅的名字:"+b.getName()+"  体形:"+b.getSize());

        a.play();

        System.out.println("重写的运行结果:");
        Pet pet = new Pet();
        System.out.println(pet);
        dog c = new dog();
        System.out.println(c);
    }
}

super关键字

super是直接父类对象的引用。
可以通过super来访问父类中被子类覆盖的方法或属性。
普通方法:没有顺序限制。可以随便调用。
构造函数中:任何类的构造函数中,若是构造函数的第一行代码没有显式的调用super(…);那么Java默认都会调用super();作为父类的初始化函数。 所以你这里的super();加不加都无所谓。

子类访问父类成员
– 访问父类构造方法
super();
super(name);
– 访问父类属性
super.name;
– 访问父类方法
super.print();

小结:
super关键字来访问父类的成员
super只能出现在子类的方法和构造方法中
super调用构造方法时,只能是第一句 super和this不能同时出现在构造方法中
super不能访问父类的private成员
super和this都不能再static方法中

// super关键字
//   super是直接父类对象的引用(通俗一点讲就是不可以继承爷爷辈)
//  用途:
//    1.可以通过super来访问父类中被子类覆盖的方法或属性,见下面代码中的a.play(); 运行出来调用的是子类中的方法,如果想调用父类中的play方法则在子类的play方法中加上super.play();
//    2.当super在普通方法中使用的话,可以任意位置编写,只是输出顺序的不同
           super.play();
           System.out.println("dog中的玩");
//         输出:Pet中的玩
//               dog中的玩
	  	       System.out.println("dog中的玩");
	           super.play();
//	          输出:dog中的玩
//	                Pet中的玩
//    3.当super在构造方法中使用的话,会默认调用父类的构造方法
           比如super(name,age,tender);
           注意的点:super一定要放在第一行
//    4.在构造方法中super关键字和this关键字不能同时出现
           可以:super(name,age,tender);
                 this.color = color;   //这里不是构造方法,只是一个普通的属性值
           但是不可以:super(name,age,tender);
                       this(); //这个好像是指向无参的构造方法
//    5.父类中的私有的属性和方法都不能被调用,包括构造方法
//    6.子类的构造方法中都会默认使用super关键字调用父类的无参构造方法(原因和存储有关)
//      在定义类的时候,无论是否自定义了其他构造方法,最好将无参构造方法写上
//    7.如果构造方法中显式的指定了super的构造方法,那么无参的构造方法就不会被调用
 

重写

在子类中可以根据需要对从基类中继承来的方法进行重写。
重写方法必须和被重写方法具有相同方法名称、参数列表和返回类型。
重写方法不能使用比被重写方法更严格的访问权限。(由于多态)

构造方法不能被继承, 因此不能重写
方法重写的规则
– 方法名相同
– 参数列表相同
– 返回值类型相同戒者是其子类;
– 访问权限不能严于父类
在这里插入图片描述

 /* 重写:@Override
 *    必须要存在继承关系,当父类中的方法无法满足子类需求的时候可以选择使用重写的方式
 *    注意:
 *         1.重写表示的是子类覆盖父类的方法,当覆盖之后,调用同样的方法的时候会优先调用子类
 *         2.重写的方法名称,返回值类型,参数列表必须跟父类一致
 *         3.子类重写的方法不允许比父类的方法具备更小的访问权限
 *            父类  public      子类  public
 *            父类  protected   子类  public protected
 *            父类  default     子类  public protected default
 *
 * 父类的静态方法子类可以调用,但不能重写
 */
 

抽象

Java中使用抽象类,限制实例化

public abstract class Pet {   
}  

抽象方法
– 抽象方法必须在抽象类里
– 抽象方法必须在子类中被实现,除非子类是抽象类

public abstract void print(); //没有方法体
package com.petrel.Abstract;

/**
 * java中的对象是对现实世界的具象化,但是在现实世界中,某些类并不具备实例化的意义,因此可以定义为抽象类
 *
 * 抽象类:
 *      1.创建抽象类的时候需要添加abstract的关键字
 *      2.不能进行实例化,也就是不能new对象
 *      3.抽象类中的某些方法需要子类进行更丰富的实现,父类实现没有意义,此时可以将抽象类中的方法
 *          定义为抽象方法,没有具体的实现,只包含方法名称,返回值,参数列表,访问修饰符
 *      4.使用abstract关键字修饰的方法叫作抽象方法,可以不写方法的实现
 *      5.子类在继承抽象父类的时候,必须要将父类中的抽象方法进行实现或者将子类也定义为抽象类
 *      6.有抽象方法的一定是抽象类,但是抽象类中不一定包含抽象方法
 */

public class AbstractTest {
    public static void main(String[] args) {
        //Pet pet = new Pet(); 这里会报错Pet中加了abstract关键字 所以Pet不能被实例化
        Dog dog = new Dog();
        dog.print();
        dog.play();
    }
}
------------
package com.petrel.Abstract;

public abstract class Pet {

    //这个宠物没必要打印,所以这个print方法实现没有意义
//    public void print(){
//
//    }

    //使用abstract关键字修饰的方法叫作抽象方法,可以不写方法的实现
    public abstract void print();

    public void play(){
        System.out.println("paly....");
    }
}
------------
package com.petrel.Abstract;

public class Dog extends Pet {

    private String gender;

    //5.子类在继承抽象父类的时候,必须要将父类中的抽象方法进行实现或者将子类也定义为抽象类
    //不写这里会报错 因为父类里面定义了一个抽象方法 当子类进行实现的时候必须把父类里面的抽象方法进行实现
    @Override
    public void print() {
        System.out.println("Dog print");

    }
}

final用法

package com.petrel.finals;

/**
 * final的使用:
 *     final可以修饰变量:表示变量的值不可变
 *     final可以修饰方法:表示方法不可以被重写
 *     final可以修饰类:表示类不可以被继承
 *              public final class finaDome {}这样写的话
 *              public class finaSubClass extends finaDome{}这个继承就会报错
 */

public class finaDome {

    public final void test(){
        System.out.println("final test");
    }

    //final可以修饰变量:表示变量的值不可变
    public static final int age = 10;
    public static void main(String[] args) {
       // age = 20;  这里的变量不可以修改
    }
}
------------
package com.petrel.finals;

public class finaSubClass extends finaDome{

/*
    //final修饰方法:方法不可以被重写
    @Override
    public final void test(){

    }*/
}

对象的比较

等于:
– 比较两基本类型变量的值是否相等
– 比较两个引用类型的值即内存地址是否相等,即是否指向同一对象。

equals() :
– 两对象的内容是否一致
示例
– object1.equals(object2) 如:p1.equals(p2)
比较所指对象的内容是否一样
是比较两个对象,而非两个基本数据类型的变量
– object1 == object2 如:p1==p2
比较p1和p2的值即内存地址是否相等,即是否是指向同一对象。

自定义类须重写equals(),否则其对象比较结果总是false。

Object类

Object类是所有Java类的根基类
重写:toString方法:
默认返回:包名+类名+@+哈希码

package com.petrel.ObjectDome;

/**
 * Object类是所有类的父类
 *
 * shift+shift 搜索Object
 *
 *native:本地、内核
 *
 * getclass
 * 反射:获取私有属性、破坏了封装
 *
 * hashCode:计算哈希值
 *
 * equals:比较属性值
 *
 * clone:克隆一个一模一样的值
 *
 * toString:return getClass().getName() + "@" + Integer.toHexString(hashCode());最后是地址
 *
 * notify、wait:线程的唤醒和等待
 *
 * finalize:回收前判断对象是否还有引用,有引用就不能回收,JVM调用
 */

public class a {

    /**
     * 重新实现hashCode方法
     * generator->Override Methods->hashCode()
     * @return
     */

    @Override
    public int hashCode() {
        return super.hashCode();
    }

}
package com.petrel.ObjectDome;

import java.util.Objects;

public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {

        return Objects.hash(name, age);
    }

    public static void main(String[] args) {
        Student s1 = new Student("zhangsan",12);
        Student s2 = new Student("zhangsan",12);
        System.out.println(s1==s2);  //比较的是地址
        System.out.println(s1.equals(s2));  //比较的是属性
    }
}

练习

在这里插入图片描述在这里插入图片描述在这里插入图片描述

package com.petrel.RentCar;

public abstract class MotoVehicle {

    private int no;
    private String brand;
    public abstract int calcRent(int day);

    public MotoVehicle(){

    }

    public MotoVehicle(int no,String brand){
        this.no = no;
        this.brand = brand;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }
}
------------
package com.petrel.RentCar;

public class Bus extends MotoVehicle {

    private int seatcount;

    public Bus(){

    }

    public Bus(int no,String brand,int seatcount) {
        super(no, brand);
        this.seatcount = seatcount;
    }

    public int getSeatcount() {
        return seatcount;
    }

    public void setSeatcount(int seatcount) {
        this.seatcount = seatcount;
    }

    @Override
    public int calcRent(int day) {
        if(seatcount>16){
            return 1500*day;
        }else{
            return 800*day;
        }
    }
}
------------
package com.petrel.RentCar;

public class Car extends MotoVehicle {

    private String type;

    public Car(){

    }

    public Car(String type){
        this.type = type;
    }

    public Car(int no,String brand,String type) {
        super(no, brand);
        this.type = type;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Override
    public int calcRent(int day) {

        if (type.equals("0")) {
            return 600 * day;
        } else if (type.equals("1")) {
            return 500 * day;
        } else if (type.equals("2")) {
            return 300 * day;
        } else {
            System.out.println("类型不匹配");
            return 0;
        }
    }
}
------------
package com.petrel.RentCar;

public class Track extends MotoVehicle {
    private int weight;

    public Track(){

    }

    public Track(int no,String brand,int weight){
        super(no,brand);
        this.weight = weight;
    }
    @Override
    public int calcRent(int day) {
        return 50*day*weight;
    }
}
------------
package com.petrel.RentCar;

public class TestMotoVehicle {
    public static void main(String[] args) {
        //MotoVehicle moto = new MotoVehicle(); 报错了,原因:抽象中可以有构造方法,但不能实例化
/*        Car car = new Car(1,"宝马","1");
        System.out.println("轿车的租金是:"+car.calcRent(5));
        Bus bus = new Bus(2,"金龙",20);
            System.out.println("客车的租金是:"+bus.calcRent(5));*/

        MotoVehicle[] moto = new  MotoVehicle[5];
        moto[0] = new Car(1,"宝马","1");
        moto[1] = new Car(1,"宝马","1");
        moto[2] = new Car(2,"别克","2");
        moto[3] = new Bus(3,"金龙",34);
        moto[4] = new Track(4,"解放",50);
        int totalMoney = calcTotal(moto);
        System.out.println("总租金:"+totalMoney);
    }

    public static int calcTotal(MotoVehicle[] moto){
        int totalMoney = 0;
        for (int i = 0;i<moto.length;i++){
            totalMoney+=moto[i].calcRent(5);
        }
        return totalMoney;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值