黑马程序员——Java语言基础:面向对象、封装(构造函数、设计模式)

时间:2023-02-11 17:28:19
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


 一、理解面向对象

面向对象和面向过程都是一种思想,面向对象是相对面向过程而言,也基于面向过程。

例如把大象装进冰箱:

面向过程强调的是功能行为:打开冰箱——>把大象装进冰箱——>关闭冰箱

Java面向对象的思想就是将功能封装进对象,强调具有功能的对象:冰箱打开,冰箱存储,冰箱关闭。

※ 面向对象的最高境界:万物皆对象(面试时慎用)。

二、类与对象

1.面向对象的三个特征:封装、继承、多态(开发就是找对象使用,没有对象则创建对象)

2.类的定义:就是对现实生活中事物的描述,是具体事物的抽象。

对象:这类事物实实在在存在的个体

例子:对汽车的描述  

class Car
{
//描述颜色
String color = "红色";
//描述轮胎数
int num = 4;
//运行行为。(方法)
void run()
{
System.out.println(color+".."+num);
}
}

※创建对象:Car c = new Car();

※将车的颜色改为蓝色:c.color = "蓝色";

※调用对象的方法:c.run();

3.成员变量和局部变量

(1)成员变量:

                a. 成员作用于整个类中。

                b. 成员变量随对象的存在而存在,在对象所在的堆内存中。

                c. 成员变量有默认初始化值。

(2)局部变量:

                a. 局部变量作用于函数或语句中。

                b. 局部变量在栈内存中。

                c. 作用的范围结束,变量空间会自动释放。

                d. 局部变量没有默认初始化值。

4.匿名对象:

(1)匿名对象是对象的简化形式。
(2)匿名对象两种使用情况

a. 当对对象方法只调用一次时,可以用匿名对象,但如果对一个对象进行多个成员调用,必须给对象起名

b. 匿名对象可以作为实际参数进行传递。

三、封装(Encapsulation)

1.概念:封装是指隐藏对象的属性和实现细节,仅对外提供公共访问方式

2.好处:a. 将变化隔离

    b. 便于使用

    c. 提高重用性

    d. 提高安全性

3.封装的表现形式之一——private(私有)

private关键字:权限修饰符,用于修饰类中的成员(成员变量,成员函数),私有只在本类中有效。

将成员变量私有化,对外提供对应的set,get方法对其进行访问。提高对数据访问的安全性。

例:

class Person
{
private int age;//年龄属性
public void setAge(int a)//提供访问方法,并判断是否有效
{
if(a>0 && a<130)
{
age = a;
speak();
}
else
System.out.println("illegal age");
}
public int getAge()
{
return age;
}
private void speak()//对象的说功能
{
System.out.println("age="+age);
}
}
class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person();
p.setAge(20);//利用封装提供的访问方法进行修改年龄属性
}
}

四、构造函数

1.特点:

       (1)函数名与类名相同。

        (2)不用定义返回值类型。

        (3)不可以写return语句。

2.作用:给对象进行初始化。

※ 当一个类中没有定义构造函数式,系统会默认给该类加入一个空参数的构造函数;只要定义了,就没有默认构造函数

※ 多个构造函数是以重载的形式存在的

例:

class Person
{
//Person(){} 未定义构造函数时

private String name;
private int age;
Person()
{
System.out.println("A:name="+name+",,age="+age);
}

Person(String n)
{
name = n;
System.out.println("B:name="+name+",,age="+age);
}

Person(String n,int a)
{
name = n;
age = a;
System.out.println("C:name="+name+",,age="+age);
}
<span style="white-space:pre"></span>//三个构造函数,重载,初始化时有可能不一样,例如孩子一出生有的无姓名,有的有
}

class PersonDemo
{
public static void main(String[] args)
{
Person p1 = new Person();
Person p2 = new Person("lisi");
Person p3 = new Person("wangwu",10);
}
}

※ 构造函数和一般函数的区别:

(1)构造函数是在对象一建立就运行,给对象初始化;一般函数对象调用才执行,给对象添加功能

(2)一个对象建立,构造函数只运行一次;一般函数可以被该对象调用多次

※ 定义构造函数的情况:当分析事物时,该事物具备一些特性或行为,那么将这些内容定义在构造函数中


3.构造代码块:对象一建立就运行,优先于构造函数执行

※ 与构造函数的区别:构造代码块给所有对象进行统一初始化,构造函数给对应的对象初始化

※ 构造代码块中定义的是不同对象的共性的初始化内容

4.this关键字:用于区*部变量和成员变量同名的情况

(1)this代表本类对象,哪个对象在调用this所在的函数,this就代表哪个对象。

(2)应用:当定义类中功能时,该函数内部要用到调用该函数的对象时,用this表示这个对象

(3)用于构造函数间互相调用(例:this(name);),只能定义在构造函数第一行,因为初始化要先执行

5.static关键字

(1) static是一个修饰符,用于修饰成员(成员变量和成员函数)。当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用,格式:类名.静态成员。

(2)特点:

        a.随着类的加载而加载。(静态会随着类的消失而消失,说明它的生命周期最长。)

        b.优先于对象存在。明确一点:静态是先存在。对象是后存在。

        c.被所有对象所共享。

        d.可以直接被类名所调用。

(3)类变量和实例变量的区别:( 静态成员变量又称为类变量;非静态成员变量又被称为实例变量

a.存放位置:

类变量随着类的加载而存在于方法区中。

实例变量随着对象的建立而存在于堆内存中。

b.生命周期:

类变量生命周期最长,随着类的消失而消失。

实例变量生命周期随着对象的消失而消失。

(4)使用注意事项:

a.静态方法只能访问静态成员;非静态方法既可以访问静态也可以访问非静态。

b.静态方法中不可以定义this,super关键字。因为静态优先于对象存在,所以静态方法中不可以出现this。

c.主函数是静态的。(主函数是一个特殊的函数且格式固定,作为程序的入口,被JVM调用)

(5)静态的利弊

利处:对对象共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。可以直接被类名调用。

弊端:生命周期过长;访问出现局限性。(静态虽好,只能访问静态)。

(6)使用静态的情况:(静态修饰的内容有成员变量和函数)

a.什么时候定义静态变量(类变量)呢?

当对象中出现共享数据时,该数据被静态所修饰,对象中的特有数据要定义成非静态存在于堆内存中。

b.什么时候定义静态函数呢?

当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定义成静态的。

(7)静态的应用:对应用程序中的共性功能进行抽取,独立封装,以便复用

※ 帮助文档:javadoc -d Myhelp -author-version ArrayTool.java

   Java中的javadoc工具就可以完成说明文档也称API的制作。

(8)静态代码块:

a.格式:

static

{

静态代码块钟的执行语句;

}

b.特点:随着类的加载而执行,只执行一次,用于给类进行初始化只执行一次,并优先于主函数

例:

class StaticCode
{
static
{
System.out.println("a");
}
}
class StaticCodeDemo
{
static
{
System.out.println("b");
}

public static void main(String[] args)
{
new StaticCode();//不创建对象,调用该类方法也可StaticCode.方法名();
new StaticCode();
System.out.println("over");
}
static
{
System.out.println("c");
}
}

//d:\>java\day6\java StaticCodeDemo

//输出结果:先执行StaticCodeDemo类中静态代码块: b c
// 再读主函数,调用StaticCode类,输出a,再调用时静态代码块不再执行
// 最后输出over
// b c a over
※ 初始化的先后顺序:类初始化(静态代码块)-->对象初始化(构造代码块)-->对应对象初始化(构造函数)

6.对象的初始化过程

创建一个新对象都做了什么事情:

a.把类名.class文件加载到内存中。

b.执行该类中的static代码块,如果有得话,给该类进行初始化。

c.在堆内存中开辟空间,分配内存地址。给对象

d.在堆内存中建立对象的特有属性。并进行默认初始化。

e.对属性进行显示初始化。

f.对对象进行构造代码块初始化。

g.对对象进行对应构造函数初始化。

h.将内存地址赋给栈内存中的对象名变量。

五、设计模式

1.设计模式是解决某一类问题最行之有效的方法,java中有23中设计模式

2.单例设计模式:解决一个类在内存中只存在一个对象。(保证对象的唯一性)

※ 为了避免其他程序过多建立该类对象,先禁止其他程序建立该类对象。

※ 同时让其他程序可以访问该类对象,只能在本类中自定义一个对象,并对外提供一些访问方式

3.单例设计模式的两种方式:

a.饿汉式:(先初始化对象,single类一进内存就已经创建好了对象)

class SingleDemo
{
//创建本类对象
private static Single s = new Single();
//构造方法
private Single(){}
//返回本类对象的方法
public static Single getInstance()
{
return s;
}

}
b.懒汉式:(single类进内存对象还不存在,只有调用方法时才建立对象,即对象的延迟加载)

class Single
{
//s为空
private static Single s = null;
//构造方法
private Single(){}
//初始化本类对象,并返回本类对象的方法
public static Single getInstance()
{
if(s==null)
{
synchronized(Single.class) //锁
{
if(s==null)
s = new Single();
}
}
return s;
}
}