1.关键字this
1.1this是什么?
在Java中,它在方法内部使用,表示调用该方法的对象(非static方法)
它在构造器内部使用,表示该构造器正在初始化的对象
this可以调用的结构:成员变量,方法和构造器。
1.2什么时候使用this
1.2.1实例方法或构造器中使用当前对象的成员
在实例方法或构造器中,当需要访问当前对象的成员变量(字段)或成员方法时,可以使用 this
关键字。特别是当参数名称与成员变量名称相同,或需要明确区分局部变量和成员变量时,this
非常有用。
使用场景:
- 区分成员变量和局部变量:当方法的参数名和类的成员变量名相同时,使用
this
关键字区分成员变量和参数。 - 调用当前对象的成员方法:在当前对象的实例方法中调用该对象的其他方法。
示例 1:在构造器中使用 this
public class Student {
private String name;
private int age;// 构造器参数与成员变量重名
public Student(String name, int age) {
this.name = name; // 使用 this 来区分成员变量 name 和局部变量 name
this.age = age;
}
}
示例 2:在实例方法中使用 this
public class Student {
private String name;
private int age;public Student(String name, int age) {
this.name = name;
this.age = age;
}public void setName(String name) {
this.name = name; // this.name 是成员变量,name 是方法参数
}public void printInfo() {
System.out.println("Name: " + this.name); // 通过 this 访问成员变量
System.out.println("Age: " + this.age);
}
}
2.面向对象特征二:继承性
2.1继承的概述
继承是类与类之间的一种关系,具体指一个类(子类)继承另一个类(父类)的属性和方法。通过继承,子类不仅可以复用父类已有的功能,还能在其基础上扩展新功能。
在 Java 中,使用 extends
关键字来表示继承关系。
public class Parent {
// 父类的属性和方法
}public class Child extends Parent {
// 子类可以直接使用父类的属性和方法
}
-
子类与父类的关系:
- 子类继承了父类的非私有属性和方法,但不能继承父类的私有成员(
private
修饰的属性和方法),不过可以通过父类提供的公共或受保护方法来间接访问这些私有成员。 - Java 只支持单继承,也就是说一个类只能继承一个直接父类。如果需要实现多个功能,可以通过接口(
interface
)来实现。
- 子类继承了父类的非私有属性和方法,但不能继承父类的私有成员(
-
继承的优势:
- 代码复用:子类可以重用父类中定义的代码,减少了重复编写代码的工作量。
- 扩展功能:子类可以在父类的基础上增加新的属性和方法,实现扩展功能。
- 提高维护性:由于公共代码集中在父类中,修改父类中的代码可以自动应用到所有子类中,提高了代码的可维护性。
-
继承的特点:
- 子类对象可以调用父类的方法和属性(非私有的),但子类对象不可以直接访问父类的私有属性和方法。
- 子类可以**重写(Override)**父类的方法,以提供适合子类的实现。
- Java 的
Object
类是所有类的超类(根类),即所有的类都直接或间接继承自Object
类。
-
继承的实现机制:
- 当创建子类对象时,首先会调用父类的构造方法,确保父类的初始化完成后,再进行子类的初始化。
- 子类构造器默认会调用父类的无参构造器,如果父类没有无参构造器,必须在子类构造器中手动调用父类的构造器(使用
super()
)。
3.方法重写
3.1方法重写的概述
方法重写是指在子类中定义一个与父类方法签名完全相同的方法(即方法名、参数列表、返回类型都相同),以替换父类中的该方法的实现。子类重写的这个方法将会覆盖父类的方法,且当子类对象调用该方法时,会执行子类的重写方法。
3.2 方法重写的条件
-
子类重写的方法必须与父类方法具有相同的:
- 方法名
- 参数列表(包括参数的顺序、类型和数量)
- 返回类型
- 修饰符(不能缩小访问权限,例如父类方法是
public
,则子类重写方法也必须是public
)
-
父类的方法必须被标记为
非私有
(private
)且不是final
,因为private
方法对子类是不可见的,而final
方法不能被修改。 -
重写的方法可以有更广的访问权限,但不能缩小。例如,父类方法是
protected
,子类可以将其重写为public
,但不能改为private
。
3.3 使用 @Override
注解
在 Java 中,推荐使用 @Override
注解来显式表明某个方法是对父类方法的重写。虽然不强制要求加上这个注解,但加上可以让编译器检查是否真正重写了父类的方法,避免拼写错误或方法签名不一致的问题。
@Override
public void someMethod() {
// 重写父类的方法
}
3.4方法重写的示例
// 父类
class Animal {
public void sound() {
System.out.println("Animal makes a sound");
}
}// 子类
class Dog extends Animal {
// 重写父类的 sound 方法
@Override
public void sound() {
System.out.println("Dog barks");
}
}public class TestOverride {
public static void main(String[] args) {
Animal animal = new Animal();
animal.sound(); // 输出: Animal makes a soundDog dog = new Dog();
dog.sound(); // 输出: Dog barks
}
}
4.super关键字的使用
4.1访问父类的构造方法
当子类继承父类时,可以通过 super()
来调用父类的构造方法。这通常用于初始化父类的成员变量或执行父类的初始化逻辑。
class Parent {
public Parent() {
System.out.println("Parent constructor");
}
}class Child extends Parent {
public Child() {
super(); // 调用父类的构造方法
System.out.println("Child constructor");
}
}public class Main {
public static void main(String[] args) {
Child child = new Child(); // 输出:Parent constructor -> Child constructor
}
}
4.2调用父类的方法或访问父类的成员变量
子类可以通过 super
关键字来调用父类中被子类覆盖的方法,或访问父类的成员变量。
class Parent {
public void display() {
System.out.println("Parent display");
}
}class Child extends Parent {
@Override
public void display() {
super.display(); // 调用父类的 display 方法
System.out.println("Child display");
}
}public class Main {
public static void main(String[] args) {
Child child = new Child();
child.display(); // 输出:Parent display -> Child display
}
}
5.面向对象特征三:多态性
5.1多态的形式和体现
5.1.1对象的多态性
理解:一个事物的多种形态。
多态性,是面向对象中最重要的概念,在Java的体现:对象的多态性,父类的引用指向子类的对象。
格式:(父类类型 :指子类继承的父类类型,或实现的接口类型)
父类类型 变量名 = 子类对象
举例:
Person p = new Student();
Object o = new Person(); // Object类型的变量o,指向Person类型的对象。
o = new Student(); //Object类型的变量o,指向Student类型的对象。
5.2多态性的使用前提
1.要有类的继承关系。
2.要有方法的重写。
6.Object类
Object
类是 Java 中所有类的父类,位于 java.lang
包中。每个类都隐式地继承自 Object
,除非明确地继承其他类。即便没有直接指定继承,Java 中的每个类都是 Object
的子类。
Object
类提供了一些基本的方法,这些方法可以在任何类中使用。
1. equals(Object obj)
-
作用:用于比较两个对象是否“相等”。
-
默认实现:
Object
类中的equals
方法是通过比较两个对象的引用地址来判断是否相等。 -
自定义实现:通常需要在自定义类中重写
equals
方法,比较对象的属性是否相等。
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
MyClass myClass = (MyClass) obj;
return this.field == myClass.field; // 自定义的相等逻辑
}
2. hashCode()
-
作用:返回对象的哈希码值。它常用于哈希表相关的数据结构(如
HashMap
、HashSet
等)。 -
默认实现:
Object
的hashCode
方法根据对象的内存地址生成哈希码。 -
自定义实现:如果重写了
equals
方法,一般也需要重写hashCode
方法,确保相等的对象有相同的哈希码。
@Override
public int hashCode() {
return Objects.hash(this.field); // 使用对象的字段生成哈希码
}
3. toString()
-
作用:返回对象的字符串表示,通常用于调试和打印。
-
默认实现:返回对象的类名加上 "@" 和对象的哈希码的十六进制表示。
-
自定义实现:通常在自定义类中会重写
toString
方法,以提供更有意义的字符串表示。
@Override
public String toString() {
return "MyClass{field=" + this.field + "}"; // 自定义的字符串表示
}
4. getClass()
-
作用:返回对象的运行时类信息(
Class
对象)。
public class Main {
public static void main(String[] args) {
MyClass myClass = new MyClass();
System.out.println(myClass.getClass().getName()); // 输出类的名称
}
}
5. clone()
-
作用:创建并返回当前对象的副本。
-
注意:默认的
clone
方法只进行“浅拷贝”,需要实现Cloneable
接口,并且可能需要重写该方法来实现深拷贝。
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // 浅拷贝
}
6. finalize()
-
作用:在对象被垃圾回收之前调用,用于资源释放。通常不建议依赖它来管理资源,因为垃圾回收不保证立即执行。
-
注意:自 Java 9 起,这个方法已经被废弃,因为更好的资源管理机制(如
try-with-resources
)已经广泛使用。
@Override
protected void finalize() throws Throwable {
// 资源清理逻辑
super.finalize();
}
7. wait()
, notify()
, notifyAll()
-
作用:这些方法用于线程间通信和同步,通常与
synchronized
关键字一起使用。wait()
:让线程进入等待状态,直到被notify()
或notifyAll()
唤醒。notify()
:唤醒一个在该对象监视器上等待的线程。notifyAll()
:唤醒所有在该对象监视器上等待的线程。
synchronized (this) {
this.wait(); // 进入等待状态
this.notify(); // 唤醒线程
}