面向对象_02
-
封装
-
概念: 封装,就是包装的意思
-
用法
java中的封装:
函数:封装了一段实现功能的代码;
类:封装了函数和成员变量;如果外界需要访问被封装的成员变量,就需要在类中提供公开的get和set方法
封装的好处:提高代码复用性;隐藏内部实现细节,提高安全性;
-
private
关键字一个访问权限修饰符,表示被修饰的成员(成员变量、函数)是私有的,只能在定义它的类中使用,不能被其他地方使用;
修饰成员变量,直接将private关键字写在成员变量的数据类型前面;
修饰函数,写在函数最前面; -
public
关键字一个访问权限修饰符,表示被修饰的成员是公开的,所有地方都能使用;
(public可以修饰成员变量、函数和类;如果修饰类,这个类的类名必须和java的文件名一致;所以一个java文件中可以写多个类,但最多只能由一个public的类;)
-
set
和get
函数格式:
set的方法名:set+变量名(变量名首字母大写)
get的方法名:get + 变量名(变量名首字母大写)
-
-
构造函数
-
概念和作用
- 概念:构造函数,又叫做构造器,就是在对象创建的时候由JVM自动调用的函数;
- 作用:构造函数就是用来在创建对象的时候给对象的成员变量赋值用的
-
写法
-
修饰符: 可以使用访问权限修饰符,不能使用static关键字修饰;
-
返回值类型: 构造函数没有返回值类型;void都不能写;
(要区分普通函数和构造函数,就看有没有返回值类型) -
函数名: 构造函数的函数名,必须和类名完全一致;
-
参数列表: 构造函数可以重载,参数列表根据需求,需要怎么写就怎么写;
-
return语句: 有return语句,也是通过return语句结束出栈;一般都不需要写;
-
-
过程
1.JVM执行时遇到new关键字,首先要到堆内存中开辟对象空间,然后将类中的成员变量加载到对象空间中,分配变量空间,赋默认值;
2.根据new关键字后面的代码,调用相应的构造函数进栈执行;
3.构造函数进栈执行,先执行隐藏步,然后执行构造函数中的代码,等构造函数结束出栈,对象创建完成
隐藏步:
1.执行super()语句,调用父类构造函数;
2.给对象空间中的成员变量显示赋值;
3.如果有构造代码块,要执行构造代码块;
-
默认构造函数
实际上,在java中,每一个类都至少有一个构造函数;一个类要创建对象,都必须要调用构造函数;
如果一个类中没有直接书写构造函数,编译器编译时会帮我们添加一个无参的构造函数,这个构造函数就是默认构造函数
一旦类中书写了构造函数,就不会再有默认构造函数;
-
使用注意
构造函数可以调用一般函数;
一般函数不能调用构造函数;
构造函数可以调用构造函数,不能通过函数名调用,必须通过this关键字调用;
在构造函数中使用this语句调用其他构造函数,this语句必须写在构造函数的第一行;
构造函数之间相互调用,不能出现交叉调用(递归调用);
如果一个类中的所有构造函数全部私有化,就不能再其他类中创建对象,只能在本类中创建对象
-
构造函数与一般函数区别
-
从书写格式上看:
构造函数: 没有返回值类型,连void都不能写;构造函数的函数名必须和类名一样;不能用static关键字修饰;
一般函数: 必须有一个返回值类型(是和构造函数最主要的区别);一般函数名不要和类名一样;可以用static修饰,也可以不要;
如果一个函数函数名和类名一样,是否是构造函数,就要看有没有返回值类型;没有,就是构造函数; -
从调用方式上看:
构造函数: 创建对象时由JVM调用的;一般函数不能调用构造函数;
一般函数: 哪里需要哪里就可以调用;构造函数里面也可以调用一般函数; -
从作用上看:
构造函数: 主要用来在创建对象的时候,给对象的成员变量赋值用的;
一般函数: 实现某个具体功能; -
从一个对象可以调用次数上看:
构造函数: 只有创建对象时会调用一次;
一般函数: 没有次数限制
-
-
部分问题
1、什么时候需要使用构造函数? 只要创建对象,都要使用构造函数; 2、什么时候需要自定义构造函数? 如果希望在创建对象时就给成员变量赋值,就需要自定义构造函数; 3、使用构造函数,可以在创建对象的时候就给对象的成员变量赋初始值,那么,有了构造函数,还需要提供get和set方法吗? 需要;因为构造函数只能在创建对象的时候赋值一次;如果以后想要改变这个值,就需要用到set函数;如果需要获取被封装的值,就需要用到get函数;
-
-
this
关键字-
概念 :表示对自身所属对象的引用,哪个对象调用this,this就指向那个对象;
-
应用
- 实现构造函数之间的相互调用;
- 在函数中区分成员变量和局部变量;
- 实际上,一个类中,所有没有使用static关键字修饰的函数,里面都有隐藏的this关键字
//需求:创建一个描述人的类,并提供比较是否是同龄人的功能; class Person//表示一个人的信息 { private int age;//年龄 public void setAge(int age){ this.age/*表示成员变量的age*/ = age; } public int getAge(){ return this.age; } /* 功能:比较是否是同龄人 两个明确: 1、函数返回值类型:是否是同龄人,只有两种结果,所以结果是boolean类型 2、函数参数列表:因为是和一个人比较是否是同龄人;所以应该接收一个Person类型的对象作为参数 */ public boolean compareByAge(Person other){ return this.age == other.age; } Person(int age){ this.age = age; } } class Test{ public static void main(String[] args) { Person p1 = new Person(10); Person p2 = new Person(11); //判断p1和p2是否是同龄人 boolean b = p1.compareByAge(p2); System.out.println(b?"是同龄人":"不是同龄人"); } }
-
-
static
关键字static:静态的,可以修饰类的成员变量和一般函数(不能修饰构造函数),表示被修饰的成员都是静态的,和类的对象无关,可以直接通过类名访问;
-
概念
静态的,可以修饰类的成员变量和一般函数(不能修饰构造函数),表示被修饰的成员都是静态的,和类的对象无关,可以直接通过类名访问;
-
静态成员变量
-
概念:使用static关键字修饰的成员变量叫做静态成员变量
-
格式:直接将static关键字写在成员变量的数据类型前面
private static String key = "KEY";
-
使用方法:静态成员变量和类的对象无关,直接通过类名调用
-
内存原理
java的内存分布: 栈内存;堆内存;方法区;本地方法区;寄存器;
方法区:就是用来保存class和静态的成员的,还有常量池等JVM加载一个类到方法区的时候,首先会分别将这个类中的静态成员变量加载到静态区域,非静态成员加载到非静态区域;然后为所有静态成员变量再静态区域中分配空间,赋默认值;所有静态成员变量赋完默认值,就开始为他们显示赋值,所有静态成员变量显示赋值结束,就表示加载完成,可以使用了。
-
特点
-
1、和类的对象无关,直接通过类名调用;
-
2、保存在方法区的静态区域,被该类的所有对象共享;
-
3、在类加载完成时就完成空间分配和赋值;
-
-
-
静态成员变量和非静态成员变量
-
1、从保存位置:
静态成员变量: 保存在方法区的静态区域
非静态成员变量: 保存在堆内存的对象空间中 -
2、从书写格式上看:
静态成员变量: 需要使用static关键字修饰,将static关键字直接写在数据类型前面;
非静态成员变量: 不需要使用static关键字修饰; -
3、从生命周期上看:
静态成员变量: 类加载的时候就分配空间和赋值;直到这个类被卸载(或者整个程序结束);
非静态成员变量: 创建对象的时候才分配空间和赋值;对象成为垃圾空间被回收的时候; -
4、从使用方法上看:
静态成员变量: 可以直接通过类名使用,和类的对象无关;
非静态成员变量: 必须通过类的对象使用; -
5、从修改后的影响范围上看:
静态成员变量: 所有对象都收到影响;
非静态成员变量: 只对这一个对象有影响;
-
-
静态函数
-
概念:被static关键字修饰的函数就是静态函数;
-
格式:直接将static关键字写在函数的返回值类型前面;
-
使用方法:静态函数和类的对象无关,直接通过类名调用
-
使用注意
1、静态函数不能调用非静态函数和非静态成员变量
2、非静态函数可以调用静态函数和静态成员变量
3、构造函数不能是静态的
4、静态函数中不能使用和对象有关的关键字
因为有些关键字,例如this,就是表示一个对象的引用的,而静态函数是没有对象就可以直接使用的,所以不能在静态函数里面使用this等关键字;
还有一个关键字:super; -
特点
1、和类的对象无关,可以直接通过类名调用
2、只能调用静态函数和静态成员变量,不能使用和类的对象有关的成员(this关键字;super关键字;非静态成员变量;非静态函数;)
3、非静态函数可以调用静态函数和非静态函数,也可以使用静态成员变量和非静态成员变量;
-
-
部分问题
1、什么时候应该使用静态函数和静态成员变量?
不需要对象,和对象无关的时候,就需要定义为静态成员;
(静态成员变量又叫做类变量、类字段;静态函数又叫做类函数、类方法)2、什么时候不能将函数定义为静态的?
如果一个函数中使用了非静态成员,就不能将其定义为静态的函数;3、为什么main函数需要定义为静态的、公开的?
因为非静态函数必须通过对象使用;而main函数时java程序的入口,再执行main函数之前时没有对象的,所以只能将他定义为静态的;
因为只有公开的访问权限,才能再任意地方被使用;而main函数是由JVM调用的,JVM和main函数不在一个类,也不在一个文件夹, 要能够访问main函数,只能将其定义为public的;
-
- 当才华还配不上野心,就静下来学习