6.Java基础知识:面向对象02

1、封装

1.1 概念: 封装,就是包装的意思

1.2 用法

  • java中的封装:

函数:封装了一段实现功能的代码;

:封装了函数和成员变量;

如果外界需要访问被封装的成员变量,就需要在类中提供公开的get和set方法

封装的好处:提高代码复用性;隐藏内部实现细节,提高安全性;

  • private关键字

一个访问权限修饰符,表示被修饰的成员(成员变量、函数)是私有的,只能在定义它的类中使用,不能被其他地方使用;

修饰成员变量,直接将private关键字写在成员变量的数据类型前面;

修饰函数,写在函数最前面;

  • public关键字

一个访问权限修饰符,表示被修饰的成员是公开的,所有地方都能使用;

public可以修饰成员变量、函数和类;如果修饰类,这个类的类名必须和java的文件名一致;所以一个java文件中可以写多个类,但最多只能由一个public的类;

  • setget函数

格式

set的方法名:set + 变量名(变量名首字母大写)

get的方法名:get + 变量名(变量名首字母大写)

2、构造函数

2.1 概念和作用

概念:构造函数,又叫做构造器,就是在对象创建的时候由JVM自动调用的函数;

作用:构造函数就是用来在创建对象的时候给对象的成员变量赋值用的

2.2 写法

修饰符: 可以使用访问权限修饰符,不能使用static关键字修饰;

返回值类型: 构造函数没有返回值类型;void都不能写;(要区分普通函数和构造函数,就看有没有返回值类型)

函数名: 构造函数的函数名,必须和类名完全一致;

参数列表: 构造函数可以重载,参数列表根据需求,需要怎么写就怎么写;

return语句: 有return语句,也是通过return语句结束出栈;一般都不需要写;

2.3 过程

1.JVM执行时遇到new关键字,首先要到堆内存中开辟对象空间,然后将类中的成员变量加载到对象空间中,分配变量空间,赋默认值;

2.根据new关键字后面的代码,调用相应的构造函数进栈执行;

3.构造函数进栈执行,先执行隐藏步,然后执行构造函数中的代码,等构造函数结束出栈,对象创建完成

隐藏步:

1.执行super()语句,调用父类构造函数;

2.给对象空间中的成员变量显示赋值;

3.如果有构造代码块,要执行构造代码块;

  • 默认构造函数

实际上,在java中,每一个类都至少有一个构造函数;一个类要创建对象,都必须要调用构造函数;

如果一个类中没有直接书写构造函数,编译器编译时会帮我们添加一个无参的构造函数,这个构造函数就是默认构造函数

一旦类中书写了构造函数,就不会再有默认构造函数;

  • 使用注意

构造函数可以调用一般函数;

一般函数不能调用构造函数;

构造函数可以调用构造函数,不能通过函数名调用,必须通过this关键字调用;

在构造函数中使用this语句调用其他构造函数,this语句必须写在构造函数的第一行;

构造函数之间相互调用,不能出现交叉调用(递归调用);

如果一个类中的所有构造函数全部私有化,就不能再其他类中创建对象,只能在本类中创建对象

2.4 构造函数与一般函数区别

  • 从书写格式上看

构造函数: 没有返回值类型,连void都不能写;构造函数的函数名必须和类名一样;不能用static关键字修饰;

一般函数: 必须有一个返回值类型(是和构造函数最主要的区别);一般函数名不要和类名一样;可以用static修饰,也可以不要;

如果一个函数函数名和类名一样,是否是构造函数,就要看有没有返回值类型;没有,就是构造函数;

  • 从调用方式上看

构造函数: 创建对象时由JVM调用的;一般函数不能调用构造函数;

一般函数: 哪里需要哪里就可以调用;构造函数里面也可以调用一般函数;

  • 从作用上看

构造函数: 主要用来在创建对象的时候,给对象的成员变量赋值用的;

一般函数: 实现某个具体功能;

  • 从一个对象可以调用次数上看

构造函数: 只有创建对象时会调用一次;

一般函数: 没有次数限制

2.5 部分问题

1、什么时候需要使用构造函数?

只要创建对象,都要使用构造函数;

2、什么时候需要自定义构造函数?

如果希望在创建对象时就给成员变量赋值,就需要自定义构造函数;

3、使用构造函数,可以在创建对象的时候就给对象的成员变量赋初始值,那么,有了构造函数,还需要提供get和set方法吗?

需要;

因为构造函数只能在创建对象的时候赋值一次;如果以后想要改变这个值,就需要用到set函数;如果需要获取被封装的值,就需要用到get函数;

3、this关键字

3.1 概念:表示对自身所属对象的引用,哪个对象调用this,this就指向那个对象;

3.2 应用

  • 实现构造函数之间的相互调用;
  • 在函数中区分成员变量和局部变量;
  • 实际上,一个类中,所有没有使用static关键字修饰的函数,里面都有隐藏的this关键字

4、static关键字

static:静态的,可以修饰类的成员变量和一般函数(不能修饰构造函数),表示被修饰的成员都是静态的,和类的对象无关,可以直接通过类名访问;

4.1 概念

静态的,可以修饰类的成员变量和一般函数(不能修饰构造函数),表示被修饰的成员都是静态的,和类的对象无关,可以直接通过类名访问;

4.2 静态成员变量

概念:使用static关键字修饰的成员变量叫做静态成员变量

格式:直接将static关键字写在成员变量的数据类型前面

private static String key = "KEY";

使用方法:静态成员变量和类的对象无关,直接通过类名调用

内存原理

java的内存分布: 栈内存;堆内存;方法区;本地方法区;寄存器;

方法区:就是用来保存class和静态的成员的,还有常量池等

JVM加载一个类到方法区的时候,首先会分别将这个类中的静态成员变量加载到静态区域,非静态成员加载到非静态区域;

然后为所有静态成员变量再静态区域中分配空间,赋默认值;

所有静态成员变量赋完默认值,就开始为他们显示赋值,所有静态成员变量显示赋值结束,就表示加载完成,可以使用了。

特点

1、和类的对象无关,直接通过类名调用;

2、保存在方法区的静态区域,被该类的所有对象共享;

3、在类加载完成时就完成空间分配和赋值;

4.3 静态成员变量和非静态成员变量

  • 从保存位置

静态成员变量: 保存在方法区的静态区域

非静态成员变量: 保存在堆内存的对象空间中

  • 从书写格式上看

静态成员变量: 需要使用static关键字修饰,将static关键字直接写在数据类型前面;

非静态成员变量: 不需要使用static关键字修饰;

  • 从生命周期上看

静态成员变量:类加载的时候就分配空间和赋值;直到这个类被卸载(或者整个程序结束);

非静态成员变量: 创建对象的时候才分配空间和赋值;对象成为垃圾空间被回收的时候;

  • 从使用方法上看

静态成员变量:可以直接通过类名使用,和类的对象无关;

非静态成员变量: 必须通过类的对象使用;

  • 从修改后的影响范围上看

静态成员变量:所有对象都收到影响;

非静态成员变量:只对这一个对象有影响;

4.4 静态函数

概念:被static关键字修饰的函数就是静态函数;

格式:直接将static关键字写在函数的返回值类型前面;

使用方法:静态函数和类的对象无关,直接通过类名调用

使用注意

1、静态函数不能调用非静态函数和非静态成员变量

2、非静态函数可以调用静态函数和静态成员变量

3、构造函数不能是静态的

4、静态函数中不能使用和对象有关的关键字

因为有些关键字,例如this,就是表示一个对象的引用的,而静态函数是没有对象就可以直接使用的,所以不能在静态函数里面使用this等关键字;

还有一个关键字:super;

特点

1、和类的对象无关,可以直接通过类名调用

2、只能调用静态函数和静态成员变量,不能使用和类的对象有关的成员(this关键字;super关键字;非静态成员变量;非静态函数;)

3、非静态函数可以调用静态函数和非静态函数,也可以使用静态成员变量和非静态成员变量;

4.5 部分问题

1.什么时候应该使用静态函数和静态成员变量?

不需要对象,和对象无关的时候,就需要定义为静态成员;
(静态成员变量又叫做类变量、类字段;静态函数又叫做类函数、类方法)

2.什么时候不能将函数定义为静态的?

如果一个函数中使用了非静态成员,就不能将其定义为静态的函数;

3.为什么main函数需要定义为静态的、公开的?

因为非静态函数必须通过对象使用;而main函数时java程序的入口,再执行main函数之前时没有对象的,所以只能将他定义为静态的;

因为只有公开的访问权限,才能再任意地方被使用;

而main函数是由JVM调用的,JVM和main函数不在一个类,也不在一个文件夹, 要能够访问main函数,只能将其定义为public的;