本文已参与「新人创作礼」活动,一起开启掘金创作之路。
面向对象(继承)
// 父类将属性和行为赠与子类
// 继承的使用场景
如果一个类已经不满足我们使用需求时(功能拓展),使用继承。
继承语法:
~class 子类 extends 父类{}
继承的应用
产生继承关系后,子类可以使用符类中的属性和方法,也可以定义子类独有的属性和方法。
继承的好处
提高代码的复用性、提高代码的拓展性
继承的特点
Java是单继承!一个类只能有一个父类!
// Animal.java
package com.laity.basicSyntax.day3.inherit.inherit1;
/**
* @author : Laity
* @Project: JavaLaity
* @Package com.laity.basicSyntax.day3.inherit.inherit1
* @date Date : 2021年11月17日 22:34
* @Description: 作为父类
*/
public class Animal {
// 使用属性
public String name;
public int age;
public String gender;
// 使用方法
public void eat(){};
public void sleep(){};
public void beat(){};
}
// Dog.java
package com.laity.basicSyntax.day3.inherit.inherit1;
/**
* @author : Laity
* @Project: JavaLaity
* @Package com.laity.basicSyntax.day3.inherit.inherit1
* @date Date : 2021年11月17日 22:36
* @Description: 子类
*/
public class Dog extends Animal{
}
// Program
package com.laity.basicSyntax.day3.inherit.inherit1;
/**
* @author : Laity
* @Project: JavaLaity
* @Package com.laity.basicSyntax.day3.inherit.inherit1
* @date Date : 2021年11月17日 22:37
* @Description: 继承的特点以及使用
*/
public class Program {
public static void main(String[] args) {
// 1.实例化一个Animal对象
Animal animal = new Animal();
// 2.进行成员访问
animal.name = "animal";
animal.gender = "male";
animal.age = 18;
animal.eat();
animal.sleep();
animal.beat();
// 3.实例化一个Dog对象
Dog dog = new Dog();
// 4.成员访问
dog.name = "dog";
dog.age = 10;
dog.gender = "male";
dog.eat();
dog.sleep();
dog.beat();
}
}
访问权限修饰符
// private private int privateVariable; // private私有权限
// default() int defaultVariable; // 默认权限
// protected protected int protectedVariable; // 受保护的权限
// public public int publicVariable;
访问权限修饰符,就是修饰符、属性的访问级别
| 当前类 | 同胞其他类 | 跨包子类 | 跨包其他类 | |
|---|---|---|---|---|
| private | √ | × | × | × |
| default(不能写出,不写权限,默认就是这个权限) | √ | √ | × | × |
| protected | √ | √ | √ | × |
| public | √ | √ | √ | √ |
方法重写
// 子类可以继承到父类的中的属性和方法,但是有一些方法,子类的实现与父类的方法可能实现的不同。
// 当父类提供的方法已经不能满足子类的需求时,子类中可以定义与父类相同的方法。
// 此时,子类方法完成对父类方法的覆盖,又叫重写(Override)
package com.laity.basicSyntax.day3.inherit.override;
/**
* @author : Laity
* @Project: JavaLaity
* @Package com.laity.basicSyntax.day3.inherit.override
* @date Date : 2021年11月18日 13:16
* @Description: 父类
*/
public class Animal {
/**
* 定义了所有的动物都会叫
*/
public void bark() {
System.out.println("bark~");
}
}
/**
* 当父类提供的方法已经不能满足子类的需求时,子类中可以定义与父类相同的方法。
* 方法重写
*/
class Dog extends Animal {
public void bark() {
System.out.println("汪汪汪~");
}
}
class Cat extends Animal {
public void bark() {
System.out.println("喵喵喵~");
}
}
@Override
一个注解,进行重写前的校验。校验这个方法是否是一个重写的方法。如果不是重写的方法,则直接报错。
public class Animal {
/**
* 定义了所有的动物都会叫
*/
public void bark() {
System.out.println("bark~");
}
}
class Dog extends Animal {
@Override
public void bark() {
System.out.println("汪汪汪~");
}
}
重写的注意事项
- 方法名字必须和父类的方法名字相同
- 参数列表必须和父类一致
- 方法的访问权限需要大于等于父类方法的访问权限
- 方法的返回值类型需要小于等于父类方法的返回值
Super关键字
有时候,子类重写父类的方法的时候,并不是要对父类的实现全盘推翻,而是对父类的方法进行拓展。
父类的方法中的实现仍然需要,但是还需要在父类方法的基础上进行拓展的实现,此时就需要使用super关键字调用父类的方法。
public class Animal {
/**
* 定义了所有的动物都会叫
*/
public void bark() {
System.out.println("bark~");
}
}
class Cat extends Animal {
@Override
public void bark() {
super.bark(); // 调用父类的实现
System.out.println("喵喵喵~");
}
}
打印结果:
bark~
喵喵喵~
继承中的构造方法
package com.laity.basicSyntax.day3.inherit.constructor;
/**
* @author : Laity
* @Project: JavaLaity
* @Package com.laity.basicSyntax.day3.inherit.constructor
* @date Date : 2021年11月18日 13:58
* @Description: 继承中的构造方法
*
* 子类对象在实例化的时候,需要优先实例化从父类继承的部分
* 体现:子类对象在实例化的时候,优先实例化父类部分,这个过程中默认调用父类中的无参构造方法,由此会导致一些问题
* 问题:
* 如果父类没有无参构造方法,或者父类的无参构造方法的访问权限不足,会导致子类对象无法实例化
* 解决:
* 1.访问权限不足:修改父类的访问权限
* 2.如果是父类中没有无参构造方法:
* 2.1 给父类添加无参构造
* 2.2 使用 super()手动调用父类中存在的构造方法
*/
public class Animal {
public Animal(){
System.out.println("Animal类的无参构造方法执行了");
}
}
class Dog extends Animal {
public Dog(){
System.out.println("Dog类的无参构造方法执行了");
}
}
Final关键字
-
可以修饰变量 表示这个变量的值不能改变 常量
-
可以修饰类 表示这个类是一个最终类,无法被继承(没有子类)
-
可以修饰方法 表示这个方法是最终方法,无法被重写
public final class Animal { public final void main(String[] args) { System.out.println("我是最终类(没有子类),也是最终方法(不能重写)"); } }
Object类
Object类是java中类层次的根类,所有的类都直接或者间接的继承自Object
toString(快捷键alt+insert)
package com.laity.basicSyntax.day3.inherit.object;
/**
* @author : Laity
* @Project: JavaLaity
* @Package com.laity.basicSyntax.day3.inherit.object
* @date Date : 2021年11月18日 14:27
* @Description: Object类
* <p>
* Object类是java中类层次的跟类,所有的类都直接或者间接的继承自Object
* 快捷键 ctrl + f12
* toString *****返回一个对象的字符串表示格式,当需要把这个对象转型为字符串的时候,会自动调用这个方法
* equals *****
* getClass 获取一个用来描述指定的类的Class对象,简单来说就是获取一个对象的类型
* hashCode 集合讲
*/
public class ObjectTest {
public static void main(String[] args) {
// toString
// equals
Animal animal = new Animal("laity",10,"男");
// getClass():获取一个用来描述指定的类的Class对象,简单来说就是获取一个对象的类型
Class<? extends Animal> aClass = animal.getClass();
System.out.println(aClass.getName()); // 获取类的名字
System.out.println(animal);
}
}
class Animal {
private String name;
private int age;
private String gender;
public Animal(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
/**
* toString 返回一个对象的字符串表示格式,当需要把这个对象转型为字符串的时候,会自动调用这个方法
*
* @return 返回的是一个字符串表示形式
*/
@Override
public String toString() {
return "{ name=" + name + ",age=" + age + ",gender=" + gender+ " }";
}
}
equals(快捷键):面向对象比较
* 自定义等值比较的规范
* 1.如果地址相同,则一定要返回true
* 2.如果obj是null,则一定要返回false
* 3.如果两个对象的类型不同,则一定要返回false
* 4.如果 a.equals(b)成立,则b.equals(a) 也必须成立
* 5.如果 a.equals(b)成立,则b.equals(c)成立,则 a.equals(c)也必须成立
== 是地址比较
package com.laity.basicSyntax.day3.inherit.object;
/**
* @author : Laity
* @Project: JavaLaity
* @Package com.laity.basicSyntax.day3.inherit.object
* @date Date : 2021年11月18日 14:27
* @Description: Object类
* <p>
* Object类是java中类层次的跟类,所有的类都直接或者间接的继承自Object
* 快捷键 ctrl + f12
* toString
* equals 对象的比较
* getClass
* hashCode 集合讲
*/
public class ObjectTest {
public static void main(String[] args) {
// toString
// equals
Animal animal = new Animal("laity", 10, "男");
// getClass():获取一个用来描述指定的类的Class对象,简单来说就是获取一个对象的类型
Class<? extends Animal> aClass = animal.getClass();
System.out.println(aClass.getName()); // 获取类的名字
System.out.println(animal);
Animal animal1 = new Animal("laity", 10, "男");
// equals
boolean ret = animal.equals(animal1);
System.out.println(ret);
}
}
class Animal {
protected String name;
protected int age;
protected String gender;
public Animal(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public Animal() {
} // 无参构造
// equals方法
/**
* 自定义规则,实现两个对象的等值比较规则
* @param obj 需要比值的对象
* @return 返回的结果
*
* 自定义等值比较的规范
* 1.如果地址相同,则一定要返回true
* 2.如果obj是null,则一定要返回false
* 3.如果两个对象的类型不同,则一定要返回false
* 4.如果 a.equals(b)成立,则b.equals(a) 也必须成立
* 5.如果 a.equals(b)成立,则b.equals(c)成立,则 a.equals(c)也必须成立
*/
@Override
public boolean equals(Object obj){
if (this==obj){
return true;
}
if (obj == null|| obj.getClass() != this.getClass()){
return false;
}
// 将参数obj强制转型为当前的类型,否则将无法访问属性
Animal o = (Animal)obj;
// 依次比较每一个属性值,是否都是完全相同的
return name.equals(o.name) && age == o.age && gender.equals(o.gender);
}
/**
* toString 返回一个对象的字符串表示格式,当需要把这个对象转型为字符串的时候,会自动调用这个方法
*
* @return 返回的是一个字符串表示形式
*/
@Override
public String toString() {
return "{ name=" + name + ",age=" + age + ",gender=" + gender + " }";
}
}
class Dog extends Animal {
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}