public static void main(String[] args) {
Person p1 = new Student("小明", 18, "男");
Person p2 = new Student("小明", 18, "男");
System.out.println(p1.equals(p2));
}
public class Person{
...
@Override //重写方法可以添加 @Override 注解,有关注解我们会在最后一章进行介绍,这个注解默认情况下可以省略
public boolean equals(Object obj) { //重写方法要求与父类的定义完全一致
if(obj == null) return false; //如果传入的对象为null,那肯定不相等
if(obj instanceof Person) { //只有是当前类型的对象,才能进行比较,要是都不是这个类型还比什么
Person person = (Person) obj; //先转换为当前类型,接着我们对三个属性挨个进行比较
return this.name.equals(person.name) && //字符串内容的比较,不能使用==,必须使用equals方法
this.age == person.age && //基本类型的比较跟之前一样,直接==
this.sex.equals(person.sex);
}
return false;
}
}
在重写Object提供的equals方法之后,就会按照我们的方式进行判断了:
java复制代码
public static void main(String[] args) {
Person p1 = new Student("小明", 18, "男");
Person p2 = new Student("小明", 18, "男");
System.out.println(p1.equals(p2)); //此时由于三个属性完全一致,所以说判断结果为真,即使是两个不同的对象
}
有时候为了方便查看对象的各个属性,我们可以将Object类提供的toString方法重写了:
java复制代码
@Override
public String toString() { //使用IDEA可以快速生成
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", profession='" + profession + '\'' +
'}';
}
这样,我们直接打印对象时,就会打印出对象的各个属性值了:
java复制代码
public static void main(String[] args) {
Person person = new Student("小明", 18, "男");
System.out.println(person);
}
public class Person {
...
public void exam(){
System.out.println("我是考试方法");
}
...
}
java复制代码
public class Student extends Person{
...
@Override
public void exam() {
System.out.println("我是学生,我就是小镇做题家,拿个 A 轻轻松松");
}
}
java复制代码
public class Worker extends Person{
...
@Override
public void exam() {
System.out.println("我是工人,做题我并不擅长,只能得到 D");
}
}
这样,不同的子类,对于同一个方法会产生不同的结果:
java复制代码
public static void main(String[] args) {
Person person = new Student("小明", 18, "男");
person.exam();
person = new Worker("小强", 18, "男");
person.exam();
}
public interface Study { //使用interface表示这是一个接口
void study(); //接口中只能定义访问权限为public抽象方法,其中public和abstract关键字可以省略
}
我们可以让类实现这个接口:
java复制代码
public class Student extends Person implements Study { //使用implements关键字来实现接口
public Student(String name, int age, String sex) {
super(name, age, sex, "学生");
}
@Override
public void study() { //实现接口时,同样需要将接口中所有的抽象方法全部实现
System.out.println("我会学习!");
}
}
java复制代码
public class Teacher extends Person implements Study {
protected Teacher(String name, int age, String sex) {
super(name, age, sex, "教师");
}
@Override
public void study() {
System.out.println("我会加倍学习!");
}
}
接口不同于继承,接口可以同时实现多个:
java复制代码
public class Student extends Person implements Study, A, B, C { //多个接口的实现使用逗号隔开
}
public interface Study {
public static final int a = 10; //接口中定义的静态变量只能是public static final的
public static void test(){ //接口中定义的静态方法也只能是public的
System.out.println("我是静态方法");
}
void study();
}
跟普通的类一样,我们可以直接通过接口名.的方式使用静态内容:
java复制代码
public static void main(String[] args) {
System.out.println(Study.a);
Study.test();
}
public class Student extends Person implements Study {
private String status; //状态,可以是跑步、学习、睡觉这三个之中的其中一种
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
//这里使用javap命令对class文件进行反编译得到 Compiled from "Status.java"
public final class com.test.Status extends java.lang.Enum<com.test.Status> {
public static final com.test.Status RUNNING;
public static final com.test.Status STUDY;
public static final com.test.Status SLEEP;
public static com.test.Status[] values();
public static com.test.Status valueOf(java.lang.String);
static {};
}
既然枚举类型是普通的类,那么我们也可以给枚举类型添加独有的成员方法:
java复制代码
public enum Status {
RUNNING("睡觉"), STUDY("学习"), SLEEP("睡觉"); //无参构造方法被覆盖,创建枚举需要添加参数(本质就是调用的构造方法)
private final String name; //枚举的成员变量
Status(String name){ //覆盖原有构造方法(默认private,只能内部使用!)
this.name = name;
}
public String getName() { //获取封装的成员变量
return name;
}
}
这样,枚举就可以按照我们想要的中文名称打印了:
java复制代码
public static void main(String[] args) {
Student student = new Student("小明", 18, "男");
student.setStatus(Status.RUNNING);
System.out.println(student.getStatus().getName());
}