Java类与对象(三)
1. 继承的定义与使用
- 继承的作用:在已有基础上进行功能的扩充,提高代码的复用性
- 关键字:extends
- 子类也被成为派生类,父类也被称为超类(Super Class)
1.1 继承的实现
继承语法:class 子类 extends 父类
举例:一个简单的继承实现
class Person{
private String name;
private int age;
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return this.age;
}
public void setAge(int age){
this.age = age;
}
}
class Student extends Person{
}
public class Test{
public static void main(String[] args){
Student stu = new Student();
stu.setName("张三");
stu.setAge(20);
System.out.println("姓名:"+stu.getName()+",年龄:"+stu.getAge());
}
}
//姓名:张三,年龄:20
当发生了类继承关系后,子类可以直接继承父类的操作,可以实现代码的复用,最低也可以维持与父类相同的功能
子类还可以进行功能的扩充(属性和方法)
举例:子类进行功能的扩充
class Student extends Person{
private String school;
public String getSchool(){
return this.school;
}
public void setSchool(){
this.school = school;
}
}
public class Test{
public static void main(String[] args){
Student stu = new Student();
stu.setName("张三");
stu.setAge(20);
stu.setSchool("西安工业大学");
System.out.println("姓名:"+stu.getName()+",年龄:"+stu.getAge()+",学校:"+stu.getSchool());
}
}
//姓名:张三,年龄:20,学校:西安工业大学
1.2 继承的限制
- 子类在实例化对象之前,一定会首先实例化父类对象。默认调用父类构造方法后在调用子类构造方法,进行子类对象初始化
举例:子类对象创建
class Person{
public Person(){
System.out.println("这是父类的构造方法");
}
}
class Student extends Person{
public Student(){
super(); //可以不写,默认调用无参构造
System.out.println("这是子类的构造方法");
}
}
public class Test{
public static void main(String[] args){
Student stu = new Student();
}
}
/*
这是父类的构造方法
这是子类的构造方法
*/
如果父类没有提供无参构造,那么这个时候使用super()明确指明你要调用的父类构造方法
1.3 继承的特征
- Java只允许单继承,不允许多继承,一个子类只能继承一个父类
举例:错误的继承
class A{}
class B{}
class c extends A,B{}
举例:为了实现C中有A和B的操作,可以采用多层继承
class A{}
class B extends A{}
class C extends B{}
**总结:**Java不允许多重继承,但是允许多层继承
在进行继承的时候,子类会继承父类的所有结构(包括私有属性、构造方法、普通方法),但是所有的非私有操作属于显示继承(可以直接调用),所有的私有属性属于隐式操作(通过setter和getter方式调用)
举例:显示继承与隐式继承
class Person{
private String name;
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
}
class Student extends Person{
public void fun(){
System.out.println(this.getName());
}
}
public class Test{
Student stu = new Student();
stu.setName("张三");
stu.fun();
}
//张三
此时父类的属性被子类所继承,但是子类能够使用的是所有非private操作,而所有的private操作无法被直接使用,所以称为隐式继承
2. 覆写(override)
- 定义:子类定义了与父类相同的方法和属性
2.1 方法的覆写
- 子类定义了与父类方法名称、参数类型及个数完全相同的方法
- 子类覆写的方法不能拥有比父类更严格的访问权限
- public > protected > default (缺省包)> private
举例:简单的覆写
class Person{
public void print(){
System.out.println("这是父类的方法");
}
}
class Student extends Person{
public void print(){
System.out.println("这是子类的方法");
}
}
public class Test{
public static void main(String[] args){
new Student().print();
}
}
//这是子类的方法
当调用某个方法,如果该方法已经被子类所覆写了,那么调用的一定是被覆写过的方法
举例:父类使用private定义的方法,子类使用public覆写
class Person{
public void fun(){
this.print();
}
private void print(){
System.out.println("这是父类的方法");
}
}
class Student extends Person{
public void print(){
System.out.println("这是子类的方法");
}
}
public class Test{
public static void main(String[] args){
new Student().fun();
}
}
//这是父类的方法
当new一个子类的对象去调用fun()方法时,子类没有该方法,去父类寻找,虽然父类的print()方法是私有的,但是父类的fun()方法和父类的print()方法在一个类中,可以调用
举例:父类中的方法被子类覆写
class Person{
public void fun(){
this.print();
}
public void print(){
System.out.println("这是父类的方法");
}
}
class Student extends Person{
public void print(){
System.out.println("这是子类的方法");
}
}
public class Test{
public static void main(String[] args){
new Student().fun();
}
}
//这是子类的方法
如果父类方法被子类覆写,那么调用的是子类方法
2.2 重载(overload)和覆写(override)的区别
区别 | 重载 | 覆写 |
---|---|---|
概念 | 方法名称相同,参数的类型及个数不同 | 方法名称、返回值类型及个数完全相同 |
范围 | 一个类 | 继承关系 |
限制 | 没有权限要求 | 子类覆写的方法不能比父类拥有更严格的访问权限 |
2.3 super关键字
- 在进行覆写的操作过程中,子类也可以使用
super.方法/super.属性
调用父类的方法或者属性
举例:使用super调用父类的同名方法
class Person{
public void print(){
System.out.println("这是父类的方法");
}
}
class Student extends Person{
public void print(){
super.print();
System.out.println("这是子类的方法");
}
}
public class Test{
public static void main(String[] args){
new Studnet().print();
}
}
/*
这是父类的方法
这是子类的方法
*/
2.4 super和this的区别
区别 | this | super |
---|---|---|
概念 | 访问本类中的属性和方法 | 由子类访问父类的属性和方法 |
查找范围 | 先查找本类,本类没有就查找父类 | 不查找本类,而是直接调用父类 |
特殊 | 表示当前对象 | 无 |
3. final关键字
1.在Java中final被称为终结器
- 使用final修饰类、方法、属性
- final成员变量必须在声明的时候初始化或在构造器中初始化,否则编译会报错
- 使用final定义的类不能有子类
- final一旦修饰一个类后,该类所有的方法都会被加上final(不包括成员变量)
final class A{} //A类不能有子类
- 使用final定义的方法不能被子类覆写
class A{
public final void fun(){}
}
- 使用final定义的变量就成为了常量,常量必须在声明时赋值,并且不能够被修改
public final int a = 100;
- 定义常量(public static final),常量全用大写字母,多个单词间以_分隔
public static final MAX_AGE = 120;
2.数据类型转换
- 两个操作数,一个为double,则另外一个自动提升为double,结果也是double
- 两个操作数,一个为float,则另外一个自动提升为float,结果也是float
- 两个操作数,一个为long,则另外一个自动提升为long,结果也是long
- 两个操作数是byte、short、int、char,两个操作数转换为int型,并且结果为int
- final修饰的类型不会发生变化
byte b1 = 1, b2 = 2, b3,b6,b8;
final byte b4= 4,b5 = 6, b7 = 9;
public void test(){
b3 = (b1 + b2); // byte = int 精度损失
b6= (b4+ b5); //byte = byte
b8= (b1 + b4); //byte = int 精度损失
b7= (b5+ b2); byte = int 精度损失
}
4. 多态
4.1 多态的表现
在Java中,多态核心表现有两点:
- 方法的多态性:
- 1.方法的重载:同一个方法名称可以根据参数列表不同去掉用不同的方法体
- 2.方法的覆写:同一个父类的方法,可能根据实例化子类的不同有不同的实现
- 对象的多态性:
- 1.对象的向上转型(自动):
父类 父类对象 = 子类实例
- 2.对象的向下转型(强制):
子类 子类对象 = (父类)父类实例
举例:向上转型
- 1.对象的向上转型(自动):
class Person{
public void print(){
System.out.println("这是父类的方法");
}
public void fun(){
System.out.println("只有父类有");
}
}
class Student extends Person{
public void print(){
System.out.println("这是子类的方法");
}
}
public class Test{
public static void main(String[] args){
Person per = new Person(); //new的是Person类的对象
per.print(); //调的是Person的方法
Person per1 = new Student(); //new的是Student对象,在这之前已经实例化Person类
per1.print(); //调用的是被父类覆写的方法
Person per2 = new Student();
per2.fun(); //子类没有,调用的是父类的方法
}
}
/*
这是父类的方法
这是子类的方法
只有父类有
*/
不管是否发生了转型,核心在于:你是new的那个类
举例:向下转型
class Person{
public void print(){
System.out.println("这是父类的方法")
}
}
class Student extends Person{
public void print(){
System.out.println("这是子类的方法");
}
public void fun(){
System.out.println("只有子类有");
}
}
public class Test{
public static void main(String[] args){
Person per = new Student();
per.print();
Student stu = (Student)per;
stu.fun();
}
}
/*
这是子类的方法
只有子类有
*/
总结:对象的向上转型有一个核心用途:操作参数统一
多态性总结:
- 对象多态性核心在于方法的覆写
- 通过向上转型接收参数的统一,向下转型实现子类扩充方法的调用
- 两个没有关系的类对象不能够进行转型,一定会产生ClassCastException