zoukankan      html  css  js  c++  java
  • Java基础 | Java继承 | 05

    继承的概念和实现

    Cat和Dog两个类中有许多共有的属性和方法,同理,如果是其他类型的动物,也会有这些共有的属性和方法,可以将这些共性的东西抽取出来,方便复用。

    Animal类就是父类,然后父类也就只有共性的方法和属性。

    只要是继承了这个父类的类,都可以使用父类中的方法和属性。

    继承:

    • 一种类与类之间的关系 A is a B
    • 使用已存在的类的定义作为基础建立新类
    • 新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类

    注意:继承就是要全盘接受父类... 也就是可以选择不用,但是不能不要..

    继承需要满足“A is a B”的关系,比如猫和轿车都有name和age的属性,但是轿车不能继承自Animal,因为不满足“A is a B”的关系。

    继承关键字: extends

    注意: 只能继承一个父类

    Animal类

    package com.imooc.animal;
    
    public class Animal {
    	private String name; // 昵称
    	private int month; // 月份
    	private String species; // 种类
    
    	public Animal() {
    
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public int getMonth() {
    		return month;
    	}
    
    	public void setMonth(int month) {
    		this.month = month;
    	}
    
    	public String getSpecies() {
    		return species;
    	}
    
    	public void setSpecies(String species) {
    		this.species = species;
    	}
    
    	// 吃东西
    	public void eat() {
    		System.out.println(this.getName() + "吃东西");
    	}
    
    }
    
    

    Cat类

    package com.imooc.animal;
    
    public class Cat extends Animal {
    	private double weight; // 体重
    
    	public double getWeight() {
    		return weight;
    	}
    
    	public void setWeight(double weight) {
    		this.weight = weight;
    	}
    
    	public void run() {
    		System.out.println(this.getName() + "是一只" + this.getSpecies()+",它在快乐的奔跑~");
    	}
    
    }
    
    
    • 子类可以访问父类非私有成员

    在子类中可以直接通过this进行访问

    • 父类不可以访问子类特有成员

    可以利用工具快速生成子类

    Dog类

    package com.imooc.animal;
    
    public class Dog extends Animal {
    	private String sex; // 性别
    
    	public String getSex() {
    		return sex;
    	}
    
    	public void setSex(String sex) {
    		this.sex = sex;
    	}
    
    	public void sleep() {
    		System.out.println(this.getName() + "现在" + this.getMonth() + "个月大,它正在睡觉~");
    	}
    }
    
    

    测试代码

    package com.imooc.test;
    
    import com.imooc.animal.Cat;
    import com.imooc.animal.Dog;
    
    public class Test {
    
    	public static void main(String[] args) {
    		Cat one = new Cat();
    		one.setName("花花");
    		one.setSpecies("中华田园猫");
    		one.eat();
    		one.run();
    		System.out.println("==================");
    		Dog two = new Dog();
    		two.setName("妞妞");
    		two.setMonth(1);
    		two.eat();
    		two.sleep();
    	}
    
    }
    
    

    方法的重写

    方法重载:

    • 同一类中
    • 方法名相同,参数列表不同(参数顺序、个数、类型)
    • 方法返回值、访问修饰符任意 只是对同名函数做出了限制!
    • 与方法的参数名无关 和参数的类型、个数有关
    public void sleep(){}
    private String sleep(String name){} 
    public void sleep(String name,int month){}
    public void sleep(int month,String name){}
         public void sleep(int name,String month){}
    

    方法重写:

    • 有继承关系的子类中

    • 方法名相同,参数列表相同(参数顺序、个数、类型),方法返回值相同 重写方法要和父类的方法完全一致

    • 访问修饰符,访问范围需要大于等于父类的访问范围

    • 与方法的参数名无关

    • 当方法返回值是void或基本数据类型时,必须相同;当返回值是引用类型时,可以是父类或其子类

    当子类重写父类方法后,子类对象调用的是重写后的方法。

    如果在子类中重新定义了父类中有的属性,那么就会以子类属性为准。

    访问修饰符的分类及作用

    • private:只允许在本类中进行访问

    • public:允许在任意位置访问

    • protected:允许在当前类、同包子类/非子类、跨包子类调用;跨包非子类不允许

    • 默认:允许在当前类、同包子类/非子类调用;跨包子类/非子类不允许调用

    super关键字

    如何判断同名的方法是父类的方法还是自己的方法呢?

    如果重写了父类方法,那么该方法肯定就是在子类中重写的,如果要调用父类的成员,就要使用super()关键字。

    super: 父类对象的引用

    package com.imooc.animal;
    
    public class Dog extends Animal {
    ...
    	public void sleep() {
    		this.eat(); // 自己重写的eat()
    		super.eat(); // 父类的eat()
    		System.out.println(this.getName() + "现在" + this.getMonth() + "个月大,它正在睡觉~");
    	}
    	
    	// 重写吃东西
    	public void eat() {
    		System.out.println(this.getName() + "最近没有食欲...");
    	}
    }
    
    

    父类的构造方法不允许被继承、不允许被重写。

    package com.imooc.animal;
    
    public class Animal {
    ...
    
    	public Animal() {
    		System.out.println("这是父类的无参构造");
    	}
    ...
    }
    
    
    package com.imooc.animal;
    
    public class Cat extends Animal {
    ...
    	public Cat() {
    		System.out.println("Cat类的无参构造");
    	}
    ...
    
    }
    
    package com.imooc.test;
    
    import com.imooc.animal.Cat;
    import com.imooc.animal.Dog;
    
    public class Test {
    
    	public static void main(String[] args) {
    		Cat one = new Cat();
    ...
    	}
    }
    
    

    new Cat(),会首先去执行Animal的无参构造,给Animal进行初始化。

    构造子类的时候会能不能只当父类的构造方法呢?

    子类构造方法默认使用父类的无参构造 super() 而且必须在第一行。

    可以使用super(参数)来指定父类的构造方法

    package com.imooc.animal;
    
    public class Animal {
    ...
        public Animal() {
    		System.out.println("这是父类的无参构造");
    	}
    
    	public Animal(String name, int month) {
    		System.out.println("这是父类的有参构造");
    	}
    ...
    }
    
    package com.imooc.animal;
    
    public class Cat extends Animal {
    ...
    	public Cat() {
        	super();
    		System.out.println("Cat类的无参构造");
    	}
    
    	public Cat(String name, int month) {
    		super(name,month);
    		System.out.println("Cat类的有参构造方法");
    	}
    ...
    	}
    }
    

    this & super

    继承的初始化顺序

    new一个子类的时候,会如上图,一直去寻找父类,然后再一层层进行实例的操作。

    访问修饰符不影响成员加载顺序,跟书写的位置有关。(不如静态成员和静态代码块,谁写在前面就先加载谁)

    Object类

    Object类:

    • Object类是所有类的父类
    • 一个类没有使用extends关键字明确标识继承关系,则默认继承Object类(包括数组)
    • Java中的每个类都可以使用Object中定义的方法

    关于equals方法

    • 默认的Object类的equals就是和 == 一致 就是比较两个引用是否指向一个对象
    • 子类可以通过重写equals方法的形式,改变比较内容

    String中的equals有进行重写,可以判断两个字符串的值是否相等

    package com.imooc.test;
    
    import com.imooc.animal.Animal;
    
    public class TestThree {
    
    	public static void main(String[] args) {
    		Animal one = new Animal("花花", 2);
    		Animal two = new Animal("花花", 2);
    
    		/*
    		 * equals测试: 1、继承Object中的equals方法时,比较的是两个引用是否指向同一个对象
    		 * 2、子类可以通过重写equals方法的形式,改变比较的内容
    		 */
    		boolean flag = one.equals(two);
    		System.out.println("one 和 two的引用比较:" + flag); // false
    		System.out.println("one 和 two的引用比较:" + (one == two)); // false
    		System.out.println("======================================");
    		String str1 = new String("hello");
    		String str2 = new String("hello");
    		flag = str1.equals(str2);
    		System.out.println("str1 和 str2的引用比较:" + flag); // true
    		System.out.println("str1 和 str2的引用比较:" + (str1 == str2)); // false
    		System.out.println("======================================");
    	}
    
    }
    
    

    可以在Animal中进行equals的重写,将相等的规则自定义。

    package com.imooc.animal;
    
    public class Animal {
    ...
    
    	public boolean equals(Object obj) {
    		if(obj==null)
    			return false;
    		Animal temp = (Animal) obj;
    		if ((this.getName() == temp.getName()) && (this.getMonth() == temp.getMonth()))
    			return true;
    		else
    			return false;
    	}
    
    }
    
    

    关于toString方法

    • 输出对象名时,默认会直接调用类中的toString
    • 继承Object中的toString方法时,输出对象的字符串表现形式:类型信息+@+地址信息
    • 子类可以通过重写toString,改变输出的内容以及表现形式
    package com.imooc.test;
    
    import com.imooc.animal.Animal;
    
    public class TestThree {
    
    	public static void main(String[] args) {
    ...
    		/*toString测试:
    		 * 1、输出对象名时,默认会直接调用类中的toString
    		 * 2、继承Object中的toString方法时,输出对象的字符串表示形式:类型信息+@+地址信息
    		 * 2、子类可以通过重写equals方法的形式,改变输出的内容以及表现形式
    		 */
    		System.out.println(one.toString()); // com.imooc.animal.Animal@6d06d69c
    		System.out.println(one); // com.imooc.animal.Animal@6d06d69c
    	}
    }
    

    可以重写Animal类的toString方法,那么输出就是该字符串。

    package com.imooc.animal;
    
    public class Animal {
    ...
    
    	public String toString() {
    		return "昵称:" + this.getName() + ";年龄:" + this.getMonth();
    	}
    
    }
    
    

    再次执行测试代码

    package com.imooc.test;
    
    import com.imooc.animal.Animal;
    
    public class TestThree {
    
    	public static void main(String[] args) {
    ...
    		/*toString测试:
    		 * 1、输出对象名时,默认会直接调用类中的toString
    		 * 2、继承Object中的toString方法时,输出对象的字符串表示形式:类型信息+@+地址信息
    		 * 2、子类可以通过重写equals方法的形式,改变输出的内容以及表现形式
    		 */
    		System.out.println(one.toString()); // 昵称:花花;年龄:2
    		System.out.println(one); // 昵称:花花;年龄:2
    	}
    }
    

    final关键字

    继承大大提高了代码的复用性和灵活性,但是有些时候,我们并不需要这个类被继承,这个方法被重写,这个变量的值被修改,那么此时就要用到关键字final。

    关键字 final:

    • final class:该类没有子类 public final class or final public class
    • final 方法:该方法不允许被子类重写,但是可以正常被子类继承使用
    • final 方法内部局部变量:只要在具体被使用之前赋值即可,一旦赋值不运行被修改

    这里的final修改局部变量,类似Cpp中的const。

    • final 成员属性:赋值过程 1、定义直接初始化 2、构造方法 3、构造代码块

    final修饰的成员属性,如果一开始只定义并没有赋值,那么只能通过以上三种方式进行赋值操作。

    • final 修饰引用: 那么就这个变量只能是这个引用,不能进行更改

    注解

    注解:

    • JDK1.5版本引入的一个特性
    • 可以声明在包、类、属性、方法、局部变量、方法参数等的前面,用来对这些元素进行说明、注释

    可以把注解理解为一种特殊的标记,在一段代码前加上注解,就是通知编译器和IDE,这段代码是有特殊含义的。

    上图代码中的@override,就告诉了编译器和IDE这是一个重写方法。然后编译器就会检查父类是否有该支持重写的方法。

    @override就是一种源码注解,就是给编译器做代码检测用的,一旦程序进入编译过程,那么该注解就会被抛弃。

    Spring框架中的@NotNull就是编译注解。

    运行时注解还可以通过反射获取到它,这种注解的存在就会影响程序运行逻辑和结果。比如Spring中的@Autowired这个注解。

    小结

    什么是继承?

    Cat和Dog两个类中有许多共有的属性和方法,同理,如果是其他类型的动物,也会有这些共有的属性和方法,可以将这些共性的东西抽取出来,方便复用。
    
    Animal类就是父类,然后父类也就只有共性的方法和属性。
    只要是继承了这个父类的类,都可以使用父类中的方法和属性。
    
    继承:
    *   一种类与类之间的关系 A is a B
    *   使用已存在的类的定义作为基础建立新类
    *   新类的定义可以增加新的数据或新的功能,也可以用父类的功能,**但不能选择性地继承父类**
    
    **注意:继承就是要全盘接受父类... 也就是可以选择不用,但是不能不要..**
    
    
    特点:
    * 利用代码复用
    * 缩短开发周期
    
    继承需要满足“A is a B”的关系,比如猫和轿车都有name和age的属性,但是轿车不能继承自Animal,因为不满足“A is a B”的关系。
    

    如何实现继承?

    关键字: extends
    **注意: 只能继承一个父类**
    
    
    
    *   子类可以访问父类非私有成员 
    在子类中可以直接通过this进行访问
    *   父类不可以访问子类特有成员
    
    可以利用工具快速生成子类
    

    方法重写 & 方法重载

    方法重载:
    *   同一类中
    *   方法名相同,参数列表不同(参数顺序、个数、类型)
    *   **方法返回值、访问修饰符任意** 只是对同名函数做出了限制!
    *   与方法的参数名无关 和参数的类型、个数有关
    
    
    方法重写:
    *   有继承关系的子类中
    *   方法名相同,参数列表相同(参数顺序、个数、类型),方法返回值相同 **重写方法要和父类的方法完全一致**
    *   访问修饰符,访问范围需要大于等于父类的访问范围
    *   与方法的参数名无关
    *   当方法返回值是void或基本数据类型时,必须相同;当返回值是引用类型时,可以是父类或其子类
    
    
    当子类重写父类方法后,子类对象调用的是重写后的方法。
    如果在子类中重新定义了父类中有的属性,那么就会以子类属性为准。
    
    

    访问修饰符

             本类  同包  子类  其他
    private   *    
    默认       *    *     
    protected *    *     *
    public    *     *    *     *
    
    同包:可以理解为“一个房间”,有无“血缘关系”都可
    子类:如果是不同包,那么有“血缘关系”就可以访问
    

    继承的初始化顺序

    父类静态成员 -> 子类静态成员 -> 父类对象构造 -> 子类对象构造
    
    new一个子类的时候,会如上图,一直去寻找父类,然后再一层层进行实例的操作。
    
    访问修饰符不影响成员加载顺序,跟书写的位置有关。(不如静态成员和静态代码块,谁写在前面就先加载谁)
    

    super关键字

    * super代表父类的引用
    super.print() // 访问父类方法
    super.name // 访问父类属性
    super() // 访问父类构造方法
    
    * 子类的构造的过程必须调用其父类的构造方法
    * 如果子类的构造中没有显式标注,则系统默认调用父类无参构造方法
    * 如果子类构造方法中既没有显示标注,且父类中没有无参构造方法,则编译出错
    * 使用super调用父类指定构造方法,必须在子类的方法的第一行
    
    
    注意:super&this在构造方法中只能选择用一个!因为它们都规定在第一行,那么就一山不能容二虎。
    

    Object类

    Object类:
    
    *   Object类是所有类的父类
    *   一个类没有使用extends关键字明确标识继承关系,则默认继承Object类(包括数组)
    *   Java中的每个类都可以使用Object中定义的方法
    

    equals & tostring

    关于equals方法
    *   默认的Object类的equals就是和 == 一致 就是比较两个引用是否指向一个对象
    *   子类可以通过重写equals方法的形式,改变比较内容
    String中的equals有进行重写,可以判断两个字符串的值是否相等
    
    关于toString方法
    *   输出对象名时,默认会直接调用类中的toString
    *   继承Object中的toString方法时,输出对象的字符串表现形式:类型信息+@+地址信息
    *   子类可以通过重写toString,改变输出的内容以及表现形式
    
    

    final关键字

    继承大大提高了代码的复用性和灵活性,但是有些时候,我们并不需要这个类被继承,这个方法被重写,这个变量的值被修改,那么此时就要用到关键字final。
    
    
    
    关键字 final:
    
    *   final class:该类没有子类 public final class or final public class
    *   final 方法:该方法不允许被子类重写,但是可以正常被子类继承使用
    *   final 方法内部局部变量:只要在具体被使用之前赋值即可,一旦赋值不运行被修改 
    
    这里的final修改局部变量,类似Cpp中的const。
    
    *   final 成员属性:赋值过程 1、定义直接初始化 2、构造方法 3、构造代码块
    
    final修饰的成员属性,如果一开始只定义并没有赋值,那么只能通过以上三种方式进行赋值操作。
    
    *   final 修饰引用: 那么就这个变量只能是这个引用,不能进行更改
    

    注解

    注解:
    *   JDK1.5版本引入的一个特性
    *   可以声明在包、类、属性、方法、局部变量、方法参数等的前面,用来对这些元素进行说明、注释
    可以把注解理解为一种特殊的标记,在一段代码前加上注解,就是通知编译器和IDE,这段代码是有特殊含义的。
    上图代码中的@override,就告诉了编译器和IDE这是一个重写方法。然后编译器就会检查父类是否有该支持重写的方法。
    

    注解分类

    按照运行机制分:
    * 源码注解
    * 编译时注解
    * 运行时注解
    
    按照来源分:
    * 来自JDK的注解 比如@override
    * 来自第三方的注解 比如spring中的注解
    * 我们自定义的注解
    
    元注解:解释注解的注解
    
  • 相关阅读:
    【★】KMP算法完整教程
    【★】KMP算法完整教程
    算法之【牛顿迭代法】
    算法之【牛顿迭代法】
    【★】Web精彩实战之
    【★】Web精彩实战之
    ★RFC标准库_目录链接
    ★RFC标准库_目录链接
    ★教师工资为什么这么低?/整理
    ★教师工资为什么这么低?/整理
  • 原文地址:https://www.cnblogs.com/Rowry/p/15095174.html
Copyright © 2011-2022 走看看