Java基础-chap3-面向对象

第三章 面向对象

3.1 面向对象概念

  • 面向过程与面向对象
    举例:
    大象装进冰箱。

    面向过程:
    打开冰箱。
    存储大象。
    关上冰箱。

    对于面向过程思想,强调的是过程(动作)

    例:C语言

    面向对象:
    冰箱打开。
    冰箱存储。
    冰箱关闭。

    对于面向对象思想,强调的是对象(实体)

    例:C++, Java, C#

  • 特点:

    • 面向对象就是一种常见的思想。符合人们的思考习惯。
    • 面向对象的出现,将复杂的问题简单化。
    • 面向对象的出现,让曾经在过程中的执行者,变成了对象中的指挥者。例:买电脑找电脑专家一起去商城
  • 面向对象语言的三个特征:

    1,封装
    2,继承
    3,多态

3.2 类与对象的关系

  • 类是用Java语言对现实生活中的事物进行的描述
    通过类的形式来体现
  • 怎么描述呢?
    对于事物描述通常只关注两方面。一个是属性,一个是行为。
  • 只要明确该事物的属性和行为并定义在类中即可。
    对象:其实就是该类事物实实在在存在的个体。
  • 类与对象之间的关系?
    类:事物的描述。
    对象:该类事物的实例。在Java中通过new来创建的。
  • 定义类其实就是在定义类中的成员
    成员:成员变量<-->属性,成员函数<-->行为
  • 成员变量局部变量的区别:
    1,成员变量定义在中,整个类中都可以访问。
    局部变量定义在函数,语句,局部代码块中,只在所属的区域有效。
    2,成员变量存在于内存的对象中,
    局部变量存在于内存的方法中。
    3,成员变量随着对象的创建而存在,随着对象的消失而消失。
    局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。
    4,成员变量都默认初始化值。
    局部变量没有默认初始化值。

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Car
{
int num;
String color;

void run()
{
System.out.println(num+"..."+color);
}
}

class CarDemo
{
public static void main(String[] args)
{
//在计算机中创建一个car的实例。通过new关键字。
Car c = new Car();// c就是一个类Car类型的引用变量,指向了该类的对象。
c.num = 4;
c.color = "red";

c.run();// 要使用对象中的内容可以通过 对象.成员的形式来完成调用。
}
}

对象的内存体现:

  • 基本数据类型参数传递和引用数据类型参数传递

    3.3 封装(Encapsulation)

  • 封装:是指隐藏对象的属性实现细节,仅对外提供公共访问方式函数、类、框架都是封装体
  • 封装的好处
    • 变化隔离
    • 便于使用
    • 提高复用性
    • 提高安全性
  • 封装原则
    • 将不需要对外提供的内容都隐藏起来
    • 把属性都隐藏,提供公共方法对其访问
  • private关键字
    • 是一个权限修饰符
    • 用于修饰成员(成员变量和成员函数)
    • 用private私有的变量只在本类中有效
  • 常用之一:
    • 将成员变量私有化,对外提供对应的set, get方法对其进行访问。提高对数据访问的安全性

3.4 构造函数

  • 构造函数:构建创造对象时调用的函数
  • 特点
    • 函数名与类名相同
    • 不用定义返回值类型
    • 没有具体的返回值
  • 作用
    • 给对象进行初始化
  • 注意
    • 一个类中如果没有定义过构造函数,那么该类中会有一个默认的空参数构造函数
    • 如果在类中定义了指定的构造函数,那么类中的默认构造函数就没有了
    • 默认构造函数的特点
    • 多个构造函数是以重载的形式存在的
    • 将一个指定类的构造函数私有化private,可以保证不让其他程序创建该类对象
  • 构造函数与一般函数的区别
    • 构造函数:对象创建时,就会调用与之对应的构造函数,对对象进行初始化
    • 一般函数:对象创建后,需要函数功能时才调用
    • 构造函数:对象创建时,调用且只调用一次
    • 一般函数:对象创建后,可以被调用多次
    • 一般函数可以调用构造函数,构造函数不能调用一般函数
    • 构造函数首字母大写,与类名相同;一般函数首字母小写,因此可以通过名称区分
    • 细节:构造函数中可以通过写return的方式来控制输入,但这种情况很少。因为当你new对象时的参数往往来源于客户通过网页形式的输入,如用户名密码等参数。这种情况下通常会有校验,所以不用再在构造函数中进行控制。
    • 对象必须要进行初始化后才能使用
  • 什么时候定义构造函数
    • 在描述事物时,该事物一存在就具备的一些内容,这些内容都定义在构造函数中
  • 构造函数的重载(overload)
    • 一个类中出现多个构造函数时,必须以重载的形式来体现,它可以给不同的对象定义不同的初始化
    • 重载是方法名相同,参数不同。
    • 参数类型顺序不相同的话是重载,相同的话不是
1
2
3
f(int x, double y),f(int y, double x)//不是重载
f(int x, double y),f(double x, int y)//是重载
f(int x, double y),f(double y, int x)//是重载
  • 构造函数内存图解(左栈右堆)

    3.5 this关键字

    • 特点:this代表其所在函数所属对象的引用。换言之,this代本类对象的引用。
      简单来说,哪个对象调用了this所在的函数,this就代表哪个对象
    • 什么时候使用this关键字?
  • 当在函数内需要用到调用该函数的对象时,就用this。例如当成员变量与局部变量重名时,可以用关键字this来区分 this.name = name;
  • this也可以用于在构造函数中调用其他构造函数。
  • 注意:
    1,一般函数无法调用构造函数。
    2,this只能定义在构造函数的第一行。因为初始化动作要先执行。

3.6 static(静态)关键字

  • static关键字
    • 同时也是修饰符,用于修饰成员(成员变量和成员函数)
  • 被修饰后的成员具备以下特点:
    • static修饰的成员随着类的加载而加载
    • static修饰的成员优先于对象存在
    • static修饰的成员被所有对象所共享
    • static修饰的是共享数据,对象中存储的是特有数据
    • static修饰的成员多了一种调用方式,可以直接被类名调用。格式:
1
Person.country//类名.静态成员
  • 使用注意
    • 静态方法只能访问静态成员(非静态既可以访问静态,又可以访问非静态)
    • 静态方法中不可以thissuper关键字
    • 主函数是静态的
  • 成员变量静态变量
    • 成员变量和静态变量区别
      1,两个变量的生命周期不同。
      成员变量随着对象的创建而存在,随着对象的被回收而释放。
      静态变量随着类的加载而存在,随着类的消失而消失。
      2,调用方式不同。
      成员变量只能被对象调用。
      静态变量可以被对象调用,还可以被类名调用。(建议用类名调用,阅读性好)
      3,别名不同。
      成员变量也称为实例变量。
      静态变量也称为类变量。
      4,数据的存储位置不同。
      成员变量数据存储在内存的对象中,所以也叫对象的特有数据。
      静态变量数据存储在方法区(共享数据区)的静态区中,所以也叫对象的共享数据。
  • 注:JVM内存划分为五个区域
    寄存器:cpu
    本地方法区:调用系统底层内容
    方法区(数据区/共享区/共享数据区):方法存储
    栈(stack):方法调用局部变量
    堆(heap):存储对象

  • 主函数的解释
    public static void main(String[] args)

    • public:因为权限必须是最大的。
    • static:虚拟机调用主函数时是不需要对象的,直接用主函数所属类名调用即可。
    • void:主函数没有具体的返回值。
    • main:函数名,不是关键字,只是一个JVM识别的固定名字。
    • String[] args:这是主函数的参数列表,是一个数组类型的参数,而且元素都是字符串类型。
    • System.out.println(args);//[Ljava.lang.String;@61064425 @右边是哈希值,@左边[表示是数组,L表示long包名java.lang,存储的是String类型的元素
    • System.out.println(args.length); //0 表示主函数创建了一个字符串类型的数组,元素个数为0,即new String[0]
  • 静态什么时候使用
    1,静态变量。
    • 当分析对象中所具备的成员变量的值都是相同的。
    • 这时这个成员就可以被静态修饰。
    • 只要数据在对象中都是不同的,就是对象的特有数据,必须存储在对象中,是非静态的。
    • 如果是相同的数据,对象不需要做修改,只需要使用即可,不需要存储在对象中,定义成静态的。
      2,静态变量。
    • 函数是否用静态修饰,就参考该函数功能是否有访问到对象中的特有数据
    • 简单点说,从源代码看,该功能是否需要访问非静态的成员变量。
    • 如果需要,该功能就是非静态的。
    • 如果不需要,就可以将该功能定义成静态的。当然,也可以定义成非静态,但是非静态需要被对象调用,而仅创建对象调用非静态的没有访问特有数据的方法,该对象的创建时没有意义的。
  • 静态代码块
    • 随着类的加载而执行。而且只执行一次
    • 作用:用于给类进行初始化。
  • 构造代码块:可以给所有对象进行初始化
  • 执行顺序(如果有对象):静态代码块-构造代码块-构造函数

3.7 单例设计模式

  • 设计模式:对问题行之有效的解决方式。其实是一种思想。
    • 单例设计模式(Singleton Pattern)。
    • 解决的问题:就是可以保证一个类在内存中的对象唯一性
      比如对于多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性。
    • 如何保证对象唯一性呢?
      1,不允许其他程序用new创建该类对象。
      2,在该类中创建一个本类实例。
      3,对外提供一个方法,让其他程序可以获取该对象。
    • 步骤:
      1,私有化该类的构造函数。private
      2,通过new在本类中创建一个本类对象。
      3,定义一个公有的方法getInstance(获取实例),将创建的对象返回。
    • 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//饿汉式(实际开发中使用较多)
class Single//类一加载,对象就已经存在了。
{
private static Single s = new Single();

private Single(){}

public static Single getInstance()
{
return s;
}
}
//懒汉式(被多线程并发访问时有可能保证不了对象的唯一性)
class Single2//类加载进来,没对象,只有调用了getInstance方法时,才会创建对象。
//延迟加载形式。
{
private static Single2 s = null;

private Single2(){}

public static Single2 getInstance()
{
if (s==null)
{
s = new Single2();
}
return s;
}
}

class SingleDemo
{
public static void main(String[] args)
{
Single s1 = Single.getInstance();
Single s2 = Single.getInstance();

System.out.println(s1==s2);
}
}

单例设计模式-内存图解

0%