1、利用继承,可以基于已存在的类构造一个新类。继承已存在的类就是复用这些类的方法和域。在此基础上,还可以添加一些新的方法和域。
2、关键字extends表明正在构造的新类派生于一个已存在的类。
3、覆盖方法:尽管子类对象拥有父类的所有域,但在子类中不能够直接访问父类的私有域。可以访问父类定义的public域。举个例子:
创建父类Person类。并提供setter以及getter。
package POJO;
/**
* @author wangtianqi
* @create 2020-08-19 15:59
*/
public class Person {
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
创建子类Student
package POJO;
/**
* @author wangtianqi
* @create 2020-08-19 16:00
*/
public class Student extends Person {
private String school;
public Student(String school) {
this.school = school;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
}
如果此时要在Student类中添加一个学生信息方法,代码将不会通过编译。因为子类无法直接使用父类的私有域。
public String StudentInformation() {
return name+","+age+","+school;
}
又因为子类可以直接使用父类的公有域,想要这个方法通过编译,可以修改为
public String StudentInformation() {
return return this.getName()+","+this.getAge()+","+this.getSchool();
}
又或者你坚持想直接使用父类的域,可以将private修饰符改为protect。使用protect修饰的域,支持被子类直接使用。但,尽管是仅仅支持子类直接使用,但也需要小心对待。因为即便如此,也有可能破坏封装性。
我们想要测试一下学生信息方法是否可以正常运行,那么就要创建一个新的Student对象。如果使用构造器对Student属性进行初始化,发现只能对school初始化。此时可以调用父类的构造方法
public Student(String name,Integer age,String school) {
super(name,age);
this.school = school;
}
此时就可以在创建Student对象时对所有属性进行初始化了。需要注意的是,如果你需要使用super关键字调用父类的构造器,那么这个语句必须是子类构造器的第一条语句。
同时还可以使用super关键字来调用父类方法。
public Student(String name,Integer age,String school) {
// super(name,age);
super.setName(name);
super.setAge(age);
this.school = school;
}
这种方式同样可以初始化student对象。
4、多态:在Java中,对象变量是多态的。一个父类变量可以引用本类的对象,同时也可以引用其任何一个子类的对象。
举个例子,Person person = new Student();
这条语句是可以正常编译的。比如这时候创建一个新的Person子类:Teacher类。同样可以Person person0 = new Teacher();
,简而言之,父类引用指向子类对象就叫做多态。
5、final类和方法:不允许扩展的类可以使用final修饰符。
6、类型强制装换:
1)只能在继承层次内进行类型转换。
2)再将父类转换为子类之前,应该使用instanceof进行检查。
7、抽象类:
1)抽象类不能被实例化。
2)抽象类中可以有非抽象的方法以及具体数据值。
3)虽然抽象类不能被实例化,但是可以定义一个抽象类的引用指向非抽象子类的对象。
8、Object,所有类的父类:
1)如果没有明确的指出父类,那么就认为Object类是这个类的父类。
2)可以使用Object类型的变量引用任何类型的变量。
3)equals方法:此方法用于检测一个对象是否等于另外一个对象。这个方法将判断两个对象是否具有相同的引用。如果两个类有相同的引用,那么它们必定相同。但是这对于大多数情况并没有什么意义。因为,多数时候想要比较的变量并没有相同的引用,而它们的属性值完全相同,这时候我们希望得到的结果是它们是相等的。所以,一般使用equals方法时,需要将它进行重写。例如,String类中就重写了equals方法,用来比较两个字符串是否相同。对于重写equals方法,java给出了一些规范:① 自反性 : 对于任何非空引用 x , x.equals(x) 应该返回 true。② 对称性 : 对于任何引用 x 和 y , 当且仅当 y . equals ( x ) 返回 true , x . equals ( y ) 也应该返回 true。③ 传递性 : 对于任何引用 x 、 y 和 z , 如果 x . equals ( y ) 返 N true, y . equals ( z ) 返回 true ,x . equals ( z ) 也应该返回 true 。④ 一致性 : 如果 x 和 y 引用的对象没有发生变化, 反复调用 x . eqimIS ( y ) 应该返回同样的结果。⑤ 对于任意非空引用 x , x . equals ( null ) 应该返回 false。
实现这些规则,java核心技术卷给出了一些建议。
4)hashCode方法:hash code是由对象导出的一个int类型的值,散列码是没有规则的。由于 hashCode 方法定义在 Object 类中, 因此每个对象都有一个默认的散列码 。一般重写equals方法都要重写hashCode方法。并且Equals 与 hashCode 的定义必须一致 : 如果 x . equals ( y ) 返回 true , 那么 x . hashCode ( ) 就必须与 y . hashCode ( ) 具有相同的值。这里给出一个简单的例子。
package POJO;
import java.util.Objects;
/**
* @author wangtianqi
* @create 2020-08-19 15:59
*/
public class Person {
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
//地址相同,代表同一个对象,那么必定相等
if (this == o) return true;
//类型不同,必定不相等
if (!(o instanceof Person)) return false;
//类型转换
Person person = (Person) o;
//比较想要比较的对象属性
return getName().equals(person.getName()) &&
getAge().equals(person.getAge());
}
//重写hashCode方法
@Override
public int hashCode() {
//在equals中比较的属性
return Objects.hash(getName(), getAge());
}
}
5)toString方法:它用于返回表示对象值得字符串。Object 类定义了 toString 方法 ,用来打印输出对象所属的类名和散列码 。如果你将任意一个对象与一个字符串用"+"串联起来,那么java编译会自动调用toString方法。如果你想要在输出这类对象时,返回类名和散列码之外的字符串,那么你可以重写toString方法。上面的例子中也包含了toString的重写例子。