chapter4 面向对象

1.认识类和对象

Java 是面向对象的编程语言,对象就是面向对象程序设计的核心。所谓对象就是真实世界中的实体,对象与实体是一一对应的,也就是说现实世界中每一个实体都是一个对象,它是一种具体的概念。对象有以下特点:
1、对象具有属性和行为。
2、对象具有变化的状态。
3、对象具有唯一性。
4、对象都是某个类别的实例
在面向对象中,类和对象是最基本、最重要的组成单元。类实际上是表示一个客观世界某类群体的一些基本特征抽象。对象就是表示一个个具体的东西。所以说类是对象的抽象,对象是类的具体
如图示,更好理解:
在这里插入图片描述
类是构造面向对象程序的基本单位,是抽取了同类对象的共同属性和方法所形成的对象或实体的“模板”。而对象是现实世界中实体的描述,对象要创建才存在,有了对象才能对对象进行操作。类是对象的模板,对象是类的实例。

2.成员变量、局部变量的区别

成员变量:定义在类中,其作用域是整个类。
局部变量:定义在方法中,其作用域仅仅是这个方法。
①作用域不同。成员变量的作用域是整个类,但是局部变量的作用域是这个方法中。②局部变量没有默认初始值,成员变量有默认初始值。③成员变量随着对象的产生而产生,随着对象的消失而消失。局部变量随着方法的产生而产生,随着方法的结束而消失。

这里查证第二点:
在这里插入图片描述
从这里可以看到,输出的时候a下面有红线,在点击那里,会看到Initializable a,从而我们可以知道了局部变量并没有默认初始值
在这里插入图片描述

从而可以看出成员变量有默认初始值

3.面向对象的封装

什么是封装?封装将类的某些信息隐藏在类内部,不允许外部程序直接访问,这些信息只能在当前这个类中才可以被访问,外部类要访问这些变量,就只能通过该类提供的方法来实现对隐藏信息的操作和访问
封装的特点:
①只能通过规定的方法(get)访问数据。
②隐藏类的实例细节,通过规定的方法(set)方便修改和实现

实现封装的具体步骤如下:
①修改属性的可见性来限制对属性的访问,一般设为 private
②为每个属性创建一对赋值(setter)方法和取值(getter)方法,一般设为 public,用于属性的读写
③在赋值和取值方法中,加入属性控制语句(对属性值的合法性进行判断)。
在这里插入图片描述
注意:将属性变成私有类型是封装的一种体现,并不能认为将属性变成private型就是封装了

4.重写与重载

重载:允许同一个类中定义多个同名方法,只要它们的形参列表不同即可,即形参的个数、形参的类型不同
方法重载的要求是两同一不同:同一个类中方法名相同,参数列表不同。至于方法的其他部分,如方法返回值类型、修饰符等,与方法重载没有任何关系
下面如图,如果形参列表相同,返回值不同,会发现有报错,表明了方法重载和返回值类型、修饰符是否相同无关
在这里插入图片描述
在这里插入图片描述
重写:在子类中如果创建了一个与父类中相同名称、相同返回值类型、相同参数列表的方法,只是方法体中的实现不同,以实现不同于父类的功能,这种方式被称为方法重写(override),又称为方法覆盖。当父类中的方法无法满足子类需求或子类具有特有功能的时候,需要方法重写。

在重写方法时,需要遵循下面的规则:
参数列表必须完全与被重写的方法参数列表相同。返回的类型必须与被重写的方法的返回类型相同(Java1.5 版本之前返回值类型必须一样,之后的 Java 版本放宽了限制,返回值类型必须小于或者等于父类方法的返回值类型)。
②访问权限不能比父类中被重写方法的访问权限更低(public>protected>default>private)。
③重写方法一定不能抛出新的检査异常或者比被重写方法声明更加宽泛的检査型异常。例如,父类的一个方法声明了一个检査异常 IOException,在重写这个方法时就不能抛出 Exception,只能拋出 IOException 的子类异常,可以抛出非检査异常。

另外还要注意以下几条:
①重写的方法可以使用 @Override 注解来标识
②父类的成员方法只能被它的子类重写。
③声明为 final 的方法不能被重写,但是可以访问调用,同样的,被final修饰的变量同样不可以被子类重新修改,只可以访问
④声明为 static 的方法不能被重写,但是子类可以调用这个方法
构造方法不能被重写。
⑥子类和父类在同一个包中时,子类可以重写父类的所有方法,除了声明为 private 和 final/static 的方法

class Person{
    public  String name;
    public static int age = 5;
    public final int id = 7;
    public Person(String name){
        this.name = name;
        display2();
    }
    public static void show1(){
        System.out.println("被static修饰的父类方法运行中......");
    }
    private void display(){
        System.out.println("私有父类方法运行中......"+name);
    }
    public void display2(){
        System.out.println("public父类方法运行中......"+name);
    }
    public final void play(){
        System.out.println("被final修饰的父类方法运行中......"+name);
    }
}
public class ZiClass extends Person{
    public static int age = 8;
    public ExtendsDemo(String name) {
        super(name);
        this.name = name;
        display2();
    }
    public void display2(){
        System.out.println("重写父类public方法,子类运行中......");
    }
    public static void show1(){
    //和父类中含有的show1方法声明一模一样,但是方法并不一样,这不可以说这是子类重写了父类的方法
        System.out.println("子类运行中......");
    }
    public static void main(String[] args) {
    /*这里利用多态,向上转型,从而父类可以调用所有的成员,如果一些方法被子
    *类重写了,那么就会调用子类的方法,通过这样就可以检验调用show1方法的时
    *候,根据运行结果,从而判断被static修饰的方法是否可以被重写
    *
        Person test = new ZiClass("wangwu");
        test.play();//调用fianl修饰的父类方法,此时仅仅可以继承,但是不可以重写,否则报错
        test.show1();//调用被static修饰的方法
    }
}

运行结果:
在这里插入图片描述

⑦子类和父类不在同一个包中时,子类只能重写父类的声明为 public 和 protected 的非 final 方法
⑧如果不能继承一个方法,则不能重写这个方法。

5.this关键字

大部分时候,普通方法访问其他方法、成员变量时无须使用 this 前缀,但如果方法里有个局部变量和成员变量同名,但程序又需要在该方法里访问这个被覆盖的成员变量,则必须使用 this 前缀
在这里插入图片描述
构造方法调用其他的构造方法,也是通过this来实现,如图,此时可以发现并this后面没有一点 . 。
在这里插入图片描述
此时有一点是值得注意的,就是上面的代码中this(name)必须要写在Person(int age,String name)构造方法中的第一行,因为要先将初始化动作执行,所以不可以放在其他动作之后,(我觉得和先将对象建立好,在执行对象的相关操作的道理是一样的)。

所以在使用this关键字中调用它的构造方法的时候,需要注意几点:
1、如果要将在当前构造方法中调用其他的构造方法的时候,需要将this(形参列表)写在当前构造方法第一行.
2、在利用this关键字调用其他的构造方法中,至少需要保证1个构造方法不会使用this关键字调用其他的构造方法。如果没有满足这一点的话,那么就会容易陷入自己调用自己的情况,从而发生报错。例如下面的例子:
在这里插入图片描述
图解:
在这里插入图片描述

6.static关键字

static关键字是用来修饰成员变量(属性)和成员函数(方法)。
被static关键字修饰的变量有以下的特点:
①被这个类的所有对象共享。此时这个静态变量就是所有对象所共有的成员变量,而且值是相同的。比如我们每一个人的国籍是中国人,如果定义一个类,然后通过构造方法,将每一个人的国籍都定义为中国人,虽然这个操作的确可以,但是在每一次创建一个对象的时候,都需要为国籍这个变量开辟空间,从而消耗内存,因此才有了通过将这个变量定义为static型,将其共享,从而减少了消耗的内存空间。
随着类的加载而加载
③优先于对象存在。这一点是基于第二点,因为先加载类,在进行对象的创建,所已有了第三点的结论。
④**可以直接被这个类访问,**而不用new创建一个对象,然后再通过这个对象来访问这个静态变量,而是直接通过 类名.静态变量(注意类名和静态变量中间有一个点) 来访问。但是,如果这个静态变量被private修饰符修饰之后,即使是通过这一种方式访问这个静态变量,也会发生发生报错。因为被private修饰符变量修饰的变量只能在类的内部访问,不可以在类的外部访问,public修饰符修饰的变量可以在类的外部访问

⑤**static修饰的方法不可以被重写,但是可以被它的子类所调用**。

System.out.println(Person.country);//没有新建一个对象,直接访问静态变量country

成员变量(不被static修饰)和静态变量(即使这个变量也是定义在类中,但是为了和成员变量区分,所以叫静态变量)的区别
①生命的周期不同。由上面可以知道,静态变量随着类的加载而加载,那么就表明了静态变量随着类的加载而创建,随着类的结束而消失。成员变量随着对象的创建而产生,随着对象的消失而消失。
②别名不同。有结论①得出,成员变量的别名是实例变量,静态变量别名是类变量。
③调用的方式不同。成员变量只能够通过创建对象, 然后用对象来访问,但是静态变量既可以通过创建对象来访问,也可以通过类直接访问。
④数据存储位置不同。成员变量是存放在堆内存的对象中,所以也叫做对象的特有数据,每一个对象的这个变量都不一定全都相同,而静态变量是存放在方法区中的静态区,所以也叫做共享数据。

static使用的注意事项
静态方法只能访问静态成员(即静态变量、静态方法)。而非静态方法既可以访问非静态方法,也可以访问静态方法
静态方法中不可以有this,super关键字。这两点都是基于静态变量是随着类的加载而加载的,当将这个静态方法加载的时候,对象还没有创建,所以有了结论①②。
主函数必须有static
static修饰的方法不可以被重写,但是可以被它的子类所继承。static修饰的变量可以被他的子类继承,以及更新

7.主函数的格式特殊之处

main() 方法定义必须是“public static void main(String[] 字符串数组参数名)”,为什么在 Java 中定义 main 方法的语法是不可改变呢?

1)public :这个字段决定了方法是否可以被外部方法调用。我们知道C语言里面的函数是运行操作系统环境中的,可以认为操作系统一个大的方法,这个方法调用了C语言的 main()。Java 中也是同样的道理,只不过 Java 的 main 方法是跑在 JVM 中的。如果不限定 public,JVM 就不能调用 main 方法。

注意:在 Java SE1.4 以前是不强制 main 方法为 public 的。当 main 方法不是 public 时,有些版本的 Java 解释器也可以执行 Java 应用程序。Java SE1.4 及以后的版本中强制 main 方法是 public。

面向对象的语言叫方法,例如 Java。面向过程的语言叫函数,例如C语言。实际上方法就是函数,函数就是方法,只是在不同的语言不同的称呼而已
2)static:在C语言中,所有的函数都可以被直接调用,main 函数相当于全局方法,没有类的概念,但在 Java 中一般先要创建一个类的对象,再通过对象调用方法,但是在执行 main 方法之前创建一个对象显然是不可能的,因为 JVM 规定 main 方法为入口方法,从 main 开始执行。static 关键字就解决了这个问题,static 关键字修饰的方法可以视为类方法,不需要创建对象就可以直接调用该方法

3)void:由于 Java 的主方法是栈中最底层的方法,所以并不存在能够接收的值,没有能接收 main 方法的返回值,所以使用 void。

为什么 Java 不能像C语言,C++ 那样返回 int 型值?

C语言的 main 函数的调用过程:首先,程序进入到入口方法之前,是发生了很多事情的。操作系统的安排,启动运行时库,运行时库再初始化好环境,然后启动你的入口函数,你的程序才正常的运行起来。等你的程序运行结束后,就退回到运行时库,然后再退回到操作系统,然后系统再调度其他程序执行。因为 main() 不是由操作系统直接调用,所以返回类型不一样也是可以理解的。可以认为运行时库就是操作系统和 main 函数的中间联系人,在C语言中由运行时库直接调用 main 函数,所以 main 函数的返回值也是运行时库接收。

在 Java 中,可以认为是操作系统→JVM→main 方法这样的调用过程,JVM 直接调用 main 方法,所以如果 main 方法有返回值,即 JVM 接收。但是 JVM 被设计为不接受任何返回值,所以 main 方法不能有返回值,只能 void。
4)String[]:类似于C语言中的参数 char**和int,Java 中数组可以记录数目,所以省去了 int 类型的参数来表示字符串个数。

因此,main() 方法定义必须是:“public static void main(String[] 字符串数组参数名) ”,这是 Java 的规范。

8.静态代码块与构造代码块

静态代码块:格式:
static{
方法体
}
并没有方法名,同时没有返回类型,同样的因为有static的关系,随着类的加载而加载,那么就会在创建对象之前输出这个代码块中方法体的信息。值得注意的是这个代码只执行了一次

构造代码块:格式:
{
方法体
}
可以发现和静态代码块相比,没有了static这个关键字。同样的我们都知道构造方法是用来对对象进行初始换,所以构造代码块和对象有关,每创建一次对象,就会执行一次构造代码块中的方法体的信息,注意的是先输出构造代码块中的信息,然后进行对象的相关操作

由此可以知道,执行的先后顺序是:①静态代码块②构造代码块③创建对象,之后进行对象的相关操作

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值