1.equals/hashcode
equals方法
当我们创建自定义类时,我们通常会重写equals
方法来比较对象的属性值。例如,如果有一个Person
类,我们可能希望比较两Person
对象的name
和age
属性:
public class Person {
private String name;
private int age;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
if (age != person.age) return false;
return name != null ? name.equals(person.name) : person.name == null;
}
}
hashCode方法
hashCode
方法返回对象的哈希码值,用于在哈希表中确定对象的存储位置。一个好的哈希函数应该尽量减少哈希碰撞。
通常,我们使用Objects.hash
方法来生成hashCode
值:
@Override
public int hashCode() {
return Objects.hash(name, age);
}
2.抽象类
抽象类的特点:
- 不能被实例化:不能直接创建抽象类的对象。
- 可以包含抽象方法:抽象方法没有实现,只声明方法签名。
- 可以包含非抽象方法:非抽象方法有具体的实现。
- 可以包含成员变量:和普通类一样,抽象类也可以有成员变量。
抽象类的使用
定义抽象类
public abstract class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
// 抽象方法,没有具体实现
public abstract void makeSound();
// 非抽象方法,有具体实现
public void eat() {
System.out.println(name + " is eating.");
}
}
继承抽象类
继承抽象类的子类必须实现所有的抽象方法,否则子类也必须声明为抽象类。
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println("Woof woof!");
}
}
抽象类的注意事项
- 抽象类不能被实例化:尝试实例化抽象类将导致编译错误。
- 抽象方法必须在子类中重写:如果子类没有重写抽象方法,子类也必须声明为抽象类。
- 抽象类可以有构造方法:尽管抽象类不能被实例化,但可以有构造方法供子类使用。
3.接口
接口的特点:
- 完全抽象:接口中的方法默认都是抽象的,没有方法体。
- 多继承:一个类可以实现多个接口,从而实现多继承的效果。
- 解耦合:接口作为规范,允许不同的实现类以统一的方式交互。
- 灵活性:接口可以在不改变实现代码的前提下,更换具体的实现类。
接口的声明与使用
声明接口
public interface Vehicle {
void start();
void stop();
}
实现接口
public class Car implements Vehicle {
@Override
public void start() {
System.out.println("Car is starting.");
}
@Override
public void stop() {
System.out.println("Car is stopping.");
}
}
接口的注意事项
- 接口方法默认是public:在声明接口方法时,可以省略
public
关键字。 - 接口不能直接实例化:必须通过实现类来使用接口。
- 实现接口的类必须实现所有方法:除非这些方法是默认方法或静态方法。
- 接口可以继承:一个接口可以继承多个其他接口。