Datawhale-Java04 面向对象编程基础

本文深入解析Java类与方法的构成,包括成员变量、成员方法、构造方法和静态成员,以及继承、多态的概念、实现和注意事项。从继承树到向上和向下转型,再到多态的覆写和Object方法的重写,为Java开发者提供全面的基础指导。
摘要由CSDN通过智能技术生成

一、类与方法

1. 成员变量

成员变量中[=值]表示可选内容,定义变量时可以为其赋值,也可以不为其赋值。

成员方法中,权限修饰符可以是 private、public,protected中的任意一个,也可以不写,主要用来控制方法的访问权限。返回值类型用来指定方法返回数据的类型,可以是任何类型,如果方法不需要返回值,则使用void关键字;一个成员方法既可以有参数,也可以没有参数,参数可以是对象,也可以是基本数据类型的变量。如果定义的方法有返回值,则必须使用return关键字返回一个指定类型的数据,并且返回值类型要与方法返回值的类型一致。

2. 成员方法

成员方法的定义
定义格式:

[权限修饰符] [返回值类型]方法名([参数类型 参数名])[throws 异常类型]{
	//方法体
	return 返回值;
}

成员方法的参数

调用方法时可以给该方法传递一个或多个值,传给方法的值叫作实参,在方法内部,接收实参的变量叫作形参,形参的声明语法与变量的声明语法一样。形参只在方法内部有效。

  • 值参数
    值参数表明实参与形参之间按值传递,当使用值参数的方法被调用时,编译器为形参分配存储单元,然后将对应的实参的值复制到形参中,由于是值类型的传递方式,所以,在方法中对值类型的形参的修改并不会影响实参。
  • 引用参数
    如果在给方法传递参数时,参数的类型是数组或者其他引用类型,那么,在方法中对参数的修改会反映到原有的数组或者其他引用类型上,这种类型的方法参数被称之为引用参数。
  • 不定长参数
    声明方法时,如果有若干个相同类型的参数,可以定义为不定长参数,该类型的参数声明如下∶
    权限修饰符 返回值类型 方法名(参数类型... 参数名)
    注意∶参数类型和参数名之间是三个点,而不是其他数量或省略号。

构造方法

构造方法是一个与类同名的方法,对象的创建就是通过构造方法完成的。每当类实例化一个对象时,类都会自动调用构造方法。

  • 构造方法没有返回类型,也不能定义为void。
  • 构造方法的名称要与本类的名称相同。
  • 构造方法的主要作用是完成对象的初始化工作,它能把定义对象的参数传给对象成员。构造方法的定义语句代码如下:
class Book{
	public Book(){  //(无参)构造方法
	}
}

在构造方法中可以为成员变量赋值,这样当实例化一个本类的对象时,相应的成员变量也将被初始化。如果类中没有明确定义构造方法,则编译器会自动创建一个不带参数的默认构造方法。

除此之外,在类中定义构造方法时,还可以为其添加一个或者多个参数,即有参构造方法,语法如下:

class Book {
	public Book(int args){  //有参构造方法
		//对成员变量进行初始化
	}
}

注意:如果在类中定义的构造方法都是有参构造方法,则编译器不会为类自动生成一个默认的无参构造方法,当试图调用无参构造方法实例化一个对象时,编译器会报错。所以只有在类中没有定义任何构造方法时,编译器才会在该类中自动创建一个不带参数的构造方法。

this关键字

在Java语言中规定使用this关键字来代表本类对象的引用,this关键字被隐式地用于引用对象的成员变量和方法。

-this关键字虽然可以调用成员变量和成员方法,但Java语言中最常规的调用方式是使用对象.成员变量对象.成员方法进行调用。

  • 事实上,this关键字引用的就是本类的一个对象,在局部变量或方法参数覆盖了成员变量时,就要添加this关键字明确引用的是类成员还是局部变量或方法参数。
  • this关键字除了可以调用成员变量或成员方法之外,还可以作为方法的返回值。
例如,在项目中创建一个类文件,在该类中定义Book类型的方法,并通过过this关键字进行返回。

static 关键字

由static修饰的变量、常量和方法分别被称作静态变量、静态常量和静态方法,也被称作类的静态成员。

  • 静态变量
    在一个class中定义的字段,我们称之为实例字段。实例字段的特点是,每个实例都有独立的字段,各个实例的同名字段互不影响。
    还有一种字段,是用static修饰的字段,称为静态字段:static field。
    实例字段在每个实例中都有自己的一个独立“空间”,但是静态字段只有一个共享“空间”,所有实例都会共享该字段。
  • 静态方法
    用static修饰的方法称为静态方法。调用实例方法必须通过一个实例变量,而调用静态方法则不需要实例变量,通过类名就可以调用。静态方法类似其它编程语言的函数。
  • 静态代码块
    在类的成员方法之外,用static修饰代码区域可以称之为静态代码块。定义一块静态代码块,可以完成类的初始化操作,在类声明时就会运行,而构造方法在new的时候才会运行。

类的主方法

主方法是类的入口点,它指定了程序从何处开始,提供对程序流向的控制。Java编译器通过主方法来执行程序。

主方法的语法如下∶

public static void main(String[] args){
		// 方法体
}

在主方法的定义中可以看到主方法具有以下特性∶

  • 主方法是静态的,所以如要直接在主方法中调用其他方法,则该方法必须也是静态的。
  • 主方法没有返回值。
  • 主方法的形参为数组。其中 args[0]~args[n] 分别代表程序的第一个参数到第n+1个参数,可以使用 args.length 获取参数的个数。

二、继承与多态

1. 继承

在java中使用extends 关键字来声明子类继承于某父类,如下:

class 父类 {
}
 
class 子类 extends 父类 {
}

通过继承,子类只需要编写额外的功能,不再需要重复代码。
注意:子类自动获得了父类的所有字段,严禁定义与父类重名的字段!

继承树

Java只允许一个class继承自一个类,因此,一个类有且仅有一个父类。只有Object特殊,它没有父类。

类似的,如果我们定义一个继承自Person的Teacher,它们的继承树关系如下:

       ┌───────────┐
       │  Object   │
       └───────────┘
             ▲
             │
       ┌───────────┐
       │  Person   │
       └───────────┘
          ▲     ▲
          │     │
┌───────────┐ ┌───────────┐
│  Student  │ │  Teacher  │
└───────────┘ └───────────┘

继承关键字

  • implements:Java除了extends,还可以用implements关键字来实现继承。Java中不支持多重继承,但是用implements可以实现多个接口,相当于使得Java具有多继承的特性。
    public interface if1 {
        public void method1();
    }
    
    public interface if2 {
        public void method2();
    }
    
    public class if3 implements if1,if2 {
    }
    
  • protected
    继承有个特点,就是子类无法访问父类的private字段或者private方法。这使得继承的作用被削弱了。为了让子类可以访问父类的字段,我们需要把private改为protected。用protected修饰的字段可以被子类访问。因此,protected关键字可以把字段和方法的访问权限控制在继承树内部,一个protected字段和方法可以被其子类,以及子类的子类所访问,
  • super
    super关键字表示父类(超类)。子类引用父类的字段时,可以用super.fieldName。例如:
    class Student extends Person {
        public String hello() {
            return "Hello, " + super.name;
        }
    }
    
    实际上,这里使用super.name,或者this.name,或者name,效果都是一样的。编译器会自动定位到父类的name字段。
    但是,在某些时候,就必须使用super。如果父类没有默认的构造方法,子类就必须显式调用super()并给出参数以便让编译器定位到父类的一个合适的构造方法。这里还顺带引出了另一个问题:即子类不会继承任何父类的构造方法。子类默认的构造方法是编译器自动生成的,不是继承的
  • final
    final的功能是将类定义为不可继承的,也可以用于修饰方法,被修饰的方法不可被子类重写。
    从Java 15开始,允许使用sealed修饰class,并通过permits明确写出能够从该class继承的子类名称。
    例如,定义一个Shape类:
    public sealed class Shape permits Rect, Circle, Triangle {
        ...
    }
    
    上述Shape类就是一个sealed类,它只允许指定的3个类继承它。如果写:
    public final class Rect extends Shape {...}
    
    是没问题的,因为Rect出现在Shapepermits列表中。但是,如果定义一个Ellipse类就会报错

向上和向下转型

向上转型是允许的,即一个引用类型为父类的变量,可以指向子类的实例。

父类类型 变量名=new 子类类型()

和向上转型相反,如果把一个父类类型强制转型为子类类型,就是向下转型(downcasting)。

子类类型 变量名=(子类类型) 父类类型的变量;

如果向下转型的父类变量本就指向子类类型,则可以转型成功,否则失败。失败的时候,Java虚拟机会报ClassCastException
为了避免向下转型出错,Java提供了instanceof操作符,可以先判断一个实例究竟是不是某种类型.。instanceof实际上判断一个变量所指向的实例是否是指定类型,或者这个类型的子类。如果一个引用变量为null,那么对任何instanceof的判断都为false

利用instanceof,在向下转型前可以先判断:

Person p = new Student();
if (p instanceof Student) {
    // 只有判断成功才会向下转型:
    Student s = (Student) p; // 一定会成功
}

从Java 14开始,判断instanceof后,可以直接转型为指定变量,避免再次强制转型。

public class Main {
    public static void main(String[] args) {
        Object obj = "hello";
        if (obj instanceof String s) {
            // 可以直接使用变量s:
            System.out.println(s.toUpperCase());
        }
    }
}

2. 多态

在继承关系中,子类如果定义了一个与父类方法签名完全相同的方法,被称为覆写(Override)

Override和Overload不同的是,如果方法签名不同,就是Overload,Overload方法是一个新方法;如果方法签名相同,并且返回值也相同,就是Override。

注意:方法名相同,方法参数相同,但方法返回值不同,也是不同的方法。在Java程序中,出现这种情况,编译器会报错。

加上@Override可以让编译器帮助检查是否进行了正确的覆写。希望进行覆写,但是不小心写错了方法签名,编译器会报错。

class Student extends Person {
    @Override
    public void run() {
        System.out.println("Student.run");
    }
}

但是@Override不是必需的。

1. 多态的概念

Java的实例方法调用是基于运行时的实际类型的动态调用,而非变量的声明类型。这个非常重要的特性在面向对象编程中称之为多态(Polymorphic)。
多态的特性就是,运行期才能动态决定调用的子类方法。对某个类型调用某个方法,执行的实际方法可能是某个子类的覆写方法。这种不确定性的方法调用具有一个非常强大的功能,就是允许添加更多类型的子类实现功能扩展,却不需要修改基于父类的代码。

2. 覆写Object方法

因为所有的class最终都继承自Object,而Object定义了几个重要的方法:

  • toString():把instance输出为String;
  • equals():判断两个instance是否逻辑相等;
  • hashCode():计算一个instance的哈希值。

在必要的情况下,我们可以覆写Object的这几个方法。在子类的覆写方法中,如果要调用父类的被覆写的方法,可以通过super来调用。继承可以允许子类覆写父类的方法。如果一个父类不允许子类对它的某个方法进行覆写,可以把该方法标记为final。用final修饰的方法不能被覆写。如果一个类不希望任何其他类继承自它,那么可以把这个类本身标记为final。用final修饰的类不能被继承。对于一个类的实例字段,同样可以用final修饰。用final修饰的字段在初始化后不能被修改。

参考:

Datawhale
廖雪峰的官方

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值