一、面向对象的概念
1、概念:面向对象是把解决的问题按照一定规则划分为多个独立的对象,然后通过调用对象的方法来解决问题。当然,一个应用程序会包含多个对象,通过多个对象的相互配合来实现应用程序的功能。这样当应用程序功能发生变动时,只需要修改个别对象就可以了,从而使代码更容易得到维护。面向对象强调的是对象,它使复杂的内容简单化了,让我们从执行者变成了指挥者。
2、特点:面向对象的特点概括起来就是继承性、封装性和多态性。
3、 封装性:封装是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界直到具体实现细节,这就是封装思想。(example:用户使用电脑,只要用手指敲击键盘就行了,不需要知道电脑内部是如何工作的。)封装隐藏了对象的属性实现的细节,仅对外提供公共访问形式。好处是将变化隔离,便于使用,提高重用性和安全性。
封装的原则:将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供公共方法对其访问。
二、类的定义
1、类与对象:类是对某一类事物的抽象描述,而对象用于表示现实中该类事物的个体。也可以说类是一组相关的属性和行为的集合(成员变量和方法)。Java中最基本的单位是类。
2、类的定义内容:类是对象的抽象,它用于描述一组对象的共同特征和行为。类中可以定义成员变量和成员方法,其中成员变量用于描述对象的特征,也被称作属性,成员方法用于描述对象的行为,可简称为方法或函数。
代码示例:
- public class Student {// class关键字表示类,后面紧跟类名,Student是类名,表示声明一个公有的学生类
- // 定义属性
- String name;// 成员变量name-->姓名,String是该变量的类型
- int age; // 成员变量age-->年龄,int是该变量的类型
- // 定义成员方法(函数)
- public void study() {// 定义一个学习方法
- System.out.println(name + "正在学习!");
- // 在成员方法study()中可以直接访问成员变量name
- }
- }
注意:在java中,定义在类中的变量被称为成员变量,定义在方法中的变量被称为局部变量,如果在某一个方法中定义的局部变量与成员变量同名,这种情况是允许的,此时方法中通过变量名访问到的是局部变量,而并非成员变量。
三、创建与使用对象
1、创建对象:程序想要完成具体的功能,仅有类是远远不够的,还需要根据类创建实例对象。在java中可以使用new关键字来创建对象。创建对象的过程也称实例化。具体格式如下:
类型 变量名=new 类名();
如创建一个Student类的对象:Student stu=new Student();
在上面代码中,“new Student() “用于创建Student类的一个实例对象,” Student stu “则是声明了一个Student类型变量stu。中间等号用于将Student对象在内存中的地址值赋值给变量stu,这样变量stu便持有了对象的引用。
2、属性的赋值和访问:
赋值语法-->变量名.属性名=属性值;
访问语法-->变量名.属性名
3、方法的调用:变量名.方法名(<param>,..),如果该方法需要参数,则加入相应的参数。
4、成员变量的默认初始化值:在实例化对象时,java虚拟机会自动为成员变量进行初始化,针对不同类型的成员变量,java虚拟机会赋予不同的初始值。
byte、short和int类型的成员变量默认初始化值为0,long类型成员变量默认初始化值为0L,float和double类型成员变量的默认初始化值分别为0.0f和0.0d,char类型默认为空字符,boolean类型默认为false,引用类型默认为null.
代码示例:
- public class Student {
- String name;// 成员变量name-->姓名,String是该变量的类型
- int age; // 成员变量age-->年龄,int是该变量的类型
- public void study() {// 定义一个学习方法
- int age = 21;// 同名的局部变量
- System.out.println(age + "岁的" + name + "正在学习!");
- }
- }
测试:
- public static void main(String[] args) {
- Student stu1 = new Student();// 创建第一个学生实例
- stu1.name = "张三";// 给第一个学生名字初始化为张三
- System.out.println(stu1.name + " " + stu1.age);// 打印第一个学生的姓名和年龄
- stu1.study();// 调用study()方法
- Student stu2 = new Student();// 创建第二个学生实例
- stu2.study();// 调用study()方法
- }
输出结果为:
张三 0
21岁的张三正在学习!
21岁的null正在学习!
简单分析:由于第一个学生对象的年龄并没有初始化,所以系统会使用默认值,int类型的默认值为0,所以输出结果为 :张三 0
由于在study()方法中定义了同名的局部变量age,所以第一个学生对象在调用该方法是访问的是局部变量的age,而不是成员变量的age。所以输出21岁的张三正在学习!
第二个学生对象由于name属性没有赋初值,所以使用默认值null,同样调用study()方法访问的是局部变量age,所以输出结果为:21岁的null正在学习!
5、成员变量和局部变量的区别:
a)在作用域上,成员变量的作用域是整个类中都可以访问,而局部变量的作用域是定义它的方法内或语句中,执行完它就会被回收。
b)初始值,成员变量有默认初始化值,局部变量是没有默认初始化值的,必须定义、赋值,然后才能使用。
c)所在内存区域,成员变量在对象里,对象在堆内存里,成员变量也在堆里,不使用的对象会被垃圾回收机制在不确定的时候回收。而局部变量在方法运行的栈内存里,会自动释放。
d)生命周期,成员变量随着对象的创建而存在,随着对象的消失而消失。局部变量随着方法的调用而存在随着方法调用完毕而消失。
四、类的封装
1、类的封装:所谓类的封装是指在定义一个类时将类中的属性私有化,即使用private关键字来修饰,私有属性只能在它所在类中被访问,为了能让外界访问私有属性需要提供一些使用public修饰的公有方法,其中包括用于获取属性值的getXXX方法和设置属性值的setXXX方法。
注意:private仅仅是封装的一种体现,不能说封装就是私有,私有的访问权限最低,只有在本类中访问有效,比如protected也可以是实现封装。封装是一种思想,将具体实现隐藏,仅对外暴露访问方式。private修饰后的成员变量和成员方法,它们都不能在其他类中直接访问。
代码示例:
- public class Student {
- private String name;// 将name属性私有化
- private int age;// 将age属性私有化
- // 下面是公有的setXXX和getXXX方法
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public void study() {
- System.out.println("正在学习的" + name + ",今年" + age + "岁。");
- }
- }
测试:
- public class Test {
- public static void main(String[] args) {
- Student stu = new Student();// 创建Student对象
- stu.setName("张三");// 调用setName()方法赋值
- stu.setAge(21);// 调用setAge()方法赋值
- stu.study();// 调用study()方法
- System.out.println(stu.getName() + " " + stu.getAge());// 获取姓名和年龄
- }
- }
输出结果为:
正在学习的张三,今年21岁。
张三 21
五、构造方法
1、前言:从前面所学知识可以发现,实例化一个对象后,如果要为这个对象中的属性赋值,必须通过直接访问对象的属性或调用setXXX方法的方式才可以。如果需要在实例化对象的同时就为这个对象的属性进行赋值,可以通过构造方法来实现。构造方法是类的一个特殊成员,它会在类实例化对象时被自动调用。
2、构造函数的满足条件:在一个类中定义的方法如果同时满足以下三个条件,该方法称为构造方法。
方法名与类名相同(大小写也要与类名一致),在方法名的前面没有返回值类型的声明(没有void),在方法中不能使用return语句返回一个值。
作用:用于给对象的属性进行初始化
代码示例:
- public class Student {
- private String name;// 将name属性私有化
- private int age;// 将age属性私有化
- public Student() {
- System.out.println("无参的构造函数被调用了");
- }
- public Student(String n) {
- name = n;
- }
- public void study() {
- System.out.println("正在学习的是" + name);
- }
- }
测试:
- public class Test {
- public static void main(String[] args) {
- Student stu1 = new Student();// 创建Student对象
- Student stu2 = new Student("张三丰");
- stu2.study();
- }
- }
输出结果为:
无参的构造函数被调用了
正在学习的是张三丰
简单分析:创建第一个学生对象的同时调用了无参的构造方法Student(),执行了方法中的打印输出语句。创建第二个学生对象的同时调用了带一个int类型参数的构造方法,执行了该方法中的语句,将实际参数传递给成员变量age,所以调用study()方法时访问的是已经初始化后的成员变量name的值。
注意:
a) 当一个类中没有定义构造函数时,系统会默认给该类加入一个空参数的构造函数。如果定义了构造函数,无论是有参还是无参,系统都不会再给默认的构造函数了。
b)重载的构造方法是根据参数列表来区分是哪个构造方法。多个构造函数以重载形式存在。
c)构造函数间的调用只能用this语句。
d) 对象一建立就会调用与之对应的构造函数。
3、构造函数的重载:与普通方法一样,构造方法也可以重载,在一个类中可以定义多个构造方法,只要每个构造方法测参数类型或参数个数不同即可。在创建对象时,可以通过调用不同的构造方法来为不同属性进行赋值。如上面代码示例中所示,根据参数的不同分别调用了不同的构造函数。
4、构造函数与一般函数的区别:
a)构造函数和一般函数书写格式上有所不同,运行上也有不同。
b)构造函数是在对象一建立就运行,给对象初始化。而一般方法是对象调用才执行,是给对象添加对象具备的功能。
c)一个对象建立,构造函数只运行一次。而一般方法可以被该对象调用多次。
在实际中,一般都要写一个空参数的构造函数。
六、this关键字
1、this:每个对象都有一个指向自己的指针,就是this。this代表所在函数所属对象的应用。简单说:哪个对象在调用this所在函数,this就代表哪个对象。
this:用于区分局部变量和成员变量同名情况。
2、三种常见用法:
(1)、 通过this关键字可以明确的去访问一个类的成员变量,解决与局部变量名称冲突问题。
- public class Student {
- private int age;// 将age属性私有化
- public Student() {
- super();
- }
- public Student(int age) {
- super();
- this.age = age;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- }
构造方法的参数被定义为age,它是一个局部变量,它与类中的成员变量名称相同,在构造方法中使用age,访问的是局部变量,但如果使用this.age,则访问的是成员变量。
(2)、通过this关键字调用成员方法。
- public class Student {
- public void study() {
- // .......
- }
- public void sleep() {
- // study();//省略this也可以
- this.study();
- }
- }
在上面sleep()方法中,使用this关键字调用study()方法。this.study();和study();效果完全一样
(3)、 构造方法是在实例化对象时被java虚拟机自动调用的,在程序中不能像调用其他方法一样去调用构造方法,但可以在构造方法中使用”this([参数1,参数2,..])”的形式来调用其它的构造方法。
- public class Student {
- private String name;
- public Student()
- {
- System.out.println("无参的构造函数被调用了");
- }
- public Student(String name)
- {
- this();//调用无参的构造方法
- System.out.println("有参的构造函数被调用了");
- }
- }
- public class Test {
- public static void main(String[] args) {
- Student stu = new Student("张三");
- }
- }
输出结果为:
无参的构造函数被调用了
有参的构造函数被调用了
3、在使用this调用构造方法时,应注意以下几点:
a) 只能在构造方法中使用this调用其它的构造方法,不能在成员方法中使用。
b) 在构造方法中,使用this调用构造方法的语句必须位于第一行,且只能出现一次。
c) 不能在一个类的两个构造方法中不能使用this互相调用。
七、垃圾回收
1、垃圾回收机制:在java中,当一个对象成为垃圾后仍会占用内存空间,时间一长,就会导致内存空间不足。针对这种情况,java引入了垃圾回收机制。Java虚拟机会自动回收垃圾对象所占用的内存空间。一个对象在成为垃圾后会暂时的保留在内存中,当这样的垃圾积累到一定程度时,java虚拟机就会启动垃圾回收器将这些垃圾对象从内存中释放,从而使程序获得更多可用的内存空间。除了等待java虚拟机进行自动垃圾回收,也可以通过调用System.gc()方法来通知java虚拟机立即进行垃圾回收。当一个对象在内存中被释放时,它的finalize()方法会被自动调用,因此可以在类中定义finalize()方法来观察对象何时被释放。