继承
新类可以在不增加自身代码的情况下,通过从现有类中继承其属性和方法来充实自身内容。
新类称为子类,现有类称为父类
继承的特点
-
子类可以称为其他类的父类
-
每个子类只能有一个父类
-
直接继承
public class Person { } public class Student extends Person { }
-
间接继承
public class MiddleStudent extends Student { }
-
Object类是所有类的父类
继承的优点
- 代码重用:子类可以继承父类已有的代码。
- 派生性:子类是父类的一种特殊形式,具有父类的共性。
- 扩展性:通过添加新的属性和方法,子类可以扩展父类的功能。
继承格式
[访问修饰符] class 子类名 extends 父类名{
子类成员变量
子类成员方法
}
继承了什么
继承使子类获得了父类的以下内容:
- 非私有的实例成员和方法。(能看见就能继承)
不能继承的有:
- 私有(private)的成员变量和成员方法。
- 构造方法(constructor)。
- 静态初始化块(static initializer)和实例初始化块(instance initializer)。
方法重写(@Override)
子类可以重写父类的方法,即提供自己的实现。使用 @Override
注解可以明确表示一个方法是重写父类的方法。
- 具有相同方法名、相同参数列表、相同返回值类型
- 重写不能缩小被重写的访问权限
示例代码:
public class Person {
public void eat() {
System.out.println("Person is eating.");
}
}
public class Student extends Person {
@Override
public void eat() {
System.out.println("Student is eating.");
}
}
隐藏/遮蔽
隐藏
父类和子类拥有相同名字的属性或者方法,父类的同名的属性或者方法形式上不见了,实际还是存在的。
隐藏是对于静态方法和成员变量(静态变量和实例变量)
-
当发生隐藏的时候,声明类型是什么类,就调用对应类的方法
-
属性只能被隐藏不能被覆盖
-
变量可以交叉隐藏
- 实例变量隐藏实例变量
class Parent { public int num = 10; } class Child extends Parent { public int num = 20; public void printNum() { System.out.println(num); // 输出子类的num,即20 } }
- 实例变量隐藏静态变量
class Parent { public static int num = 10; } class Child extends Parent { public int num = 20; public void printNum() { System.out.println(num); // 输出子类的num,即20 } }
- 静态变量隐藏实例变量
class Parent { public int num = 10; } class Child extends Parent { public static int num = 20; public void printNum() { System.out.println(num); // 输出子类的num,即20 } }
- 静态变量隐藏静态变量
class Parent { public static int num = 10; } class Child extends Parent { public static int num = 20; public void printNum() { System.out.println(num); // 输出子类的num,即20 } }
-
子类静态方法隐藏父类静态方法(静态隐藏非静态会编译报错)
class Parent { public static void println(){ System.out.println(20); } } class Child extends Parent { public static void println(){ System.out.println(10);//隐藏了父类 } }
遮蔽:
局部变量遮蔽成员变量,当一个方法中的参数或者局部变量和成员变量同名时,方法内部就无法直接访问该成员变量,需要用this关键字来解决。
super 和 this
this
谁调用就是谁
解决:变量名和外层作用域具有相同变量名,造成的遮蔽(就近原则)问题,区分成员变量和局部变量。
用于
1.引用当前对象的变量名
public class person{
private String name;
public void SetName(String name){
this.name = name;
}
}
2.调用当前对象的成员方法
public class person{
public void sayHello(){
System.out.println("Hello");
}
public void sayHi(){
this.sayHello();
}
}
3.调用当前对象的构造方法
public class person{
private String name;
private Integer age;
public Person(String name,Integer age){
this.name = name;
this.age = age;
}
public Person(){
this("甜甜",20);
}
}
-
只能在构造方法的第一个有效语句使用
-
this关键字只能在类的实例方法和构造方法中使用。
super
子类用super来访问父类中被隐藏的成员、调用父类的构造方法
用于:
-
调用父类的构造方法:super([实参列表])
-
调用父类属性和构造方法:super.<父类字段名/方法名>
注意:
-
子类默认在构造方法的第一行调用父类的无参构造,调用可以省略
-
如果父类没有无参构造,需要在每个构造方法的第一行,通过super来调用父类的构造方法
-
super、this 不能同时出现
super/this区别
-
调用方法不同:this访问本类中的方法,包括从父类继承的方法,
super访问父类的方法
-
调用构造不同:this调用的是本类的构造方法,必须放在构造的首行,
super调用父类构造,必须放在子类构造首行。如果表示调用父类的无参构造,super可以省略
3.调用字段不同:this访问本类中的字段,包括从父类继承的字段。
super访问父类的字段
4.使用:在实例方法中可以使用,在static方法中不能使用
this:每个类都有this
super:只能出现在子类中
final 的使用
final 是 Java 中的关键字,可以修饰类、方法和变量。
- 当应用于类时,表示该类不能被继承。
- 当应用于方法时,表示该方法不能被子类重写。可以重载、可以继承。
- 当应用于变量时,表示该变量是一个常量,只能被赋值一次。可以继承
object类
Object
是 Java 中所有类的根类,它定义了一些常用的方法供其他类继承和使用。以下是一些常用的 Object
方法:
toString()
:返回对象的字符串表示形式。可以根据需要进行重写。finalize()
(JDK 9 开始已弃用):在对象被垃圾回收之前调用。不建议在代码中使用该方法。getClass()
:返回对象的运行时类。hashCode()
:返回对象的哈希码。equals(Object obj)
:比较对象是否相等。通常需要与hashCode()
方法一起重写。clone()
:创建并返回对象的浅拷贝副本。需要实现Cloneable
接口。
实例化的过程
在 Java 中,实例化一个对象的过程主要分为以下几个步骤:
分配内存空间,创建对象。
调用父类的构造方法(从顶级父类开始)。
按声明顺序依次初始化成员变量(包括父类的成员变量)。
执行构造方法的代码块和构造方法体。
返回创建的对象的引用。
在创建一个类的实例时,Java 会按照以下顺序执行:(先父后子)
- 加载类
- 执行父类的静态初始化块(如果有)。
- 执行子类的静态初始化块(如果有)。
- 执行父类的实例初始化块(如果有)。
- 执行父类的构造方法。
- 执行子类的实例初始化块(如果有)。
- 执行子类的构造方法。
例:
-
方法重写后就要使用重写的方法
-
方法调用时,static看在哪个类里,static属于类
-
方法调用时,实例看哪个对象调用,实例属于对象