您的位置:首页 > 职场人生

黑马程序员——面向对象

2015-02-04 21:59 190 查看
-------android培训java培训、期待与您交流!
----------

一、面向对象

1.1、面向对象的概念

理解面向对象:
(1).面向对象是相对面向过程而言。
(2).面向对象和面向过程都是一种思想。
(3).面向过程:强调的是功能行为。
(4).面向对象:将功能封装进对象,强调具备了功能的对象。
(5).面向对象是基于面向过程的。
面向对象特点:
(1).是一种符合人们思考习惯的思想
(2).可以将复杂的事情简单化.
(3).将程序员从执行者转换成了指挥者
(4).完成需求时:

先要去找具有所需的功能的对象来用。

如果该对象不存在,那么创建一个具有所需功能的对象。

这样简化开发并提高复用。

面向对象开发过程:其实就是不断的创建对象,使用对象, 指挥对象做事情。

面向对象过程:其实就是在管理和维护对象之间的关系。

面向对象的特征:



(1).封装(encapsulation)

(2).继承(inheritance)

(3).多态(polymorphism)

这三个特征在后面会有详细说明。

1.2、类与对象的关系

先说个例子吧:学校里的每个学生都有学号、姓名、性别、年龄等属性,所以就会根据这些共有的属性抽象出来一个类型,就是学生类。这样如果要描述一个学生的时候,也会从这些方面进行描述,这个学生的学号是多少,叫什么名字,性别是男是女,年龄多少等等。通过这样的描述,就知道这个学生了。

对应到Java语言:学生类对应class,class里面定义字段(学号,姓名、性别、年龄等);根据定义的class具

体描述就得到一个对象(学号="123456";姓名="张三";性别="男";年龄=22。。。)。

所以说:

使用计算机语言就是不断的在描述现实生活中 的事物。

java中描述事物通过类的形式体现,类是具体事物的抽象,概念上的定义。

对象即是该类事物实实在在存在的个体。

类与对象关系图例:





理解:图纸就是类;汽车就是对象。

类的定义:
其实定义类就是描述事物的属性和行为。如:人有身高、体重等属性,有吃饭、睡觉等行为。
生活中描述事物和Java中描述事物其实一样的,只是生活中用我们人类的语言来描述(中国人用中文描述;美国

人用英文描述);Java中用java语言来描述。

Java中用类class来描述事物:

属性:对应类中的成员变量。

行为:对应类中的成员函数。

也就是说定义类就是在定义类中的成员(成员变量和成员函数)。

成员变量和局部变量的区别:

成员变量:

(1).成员变量定义在类中,在整个类中都可以被访问。

(2).成员变量随着对象的建立而建立,存在于对象所在的堆内存中。

(3).成员变量有默认初始化值。

局部变量:

(1).局部变量只定义在局部范围内,如:函数内,语句内等。

(2).局部变量存在于栈内存中。

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

(4).局部变量没有默认初始化值。

匿名对象:是对象的简化形式

使用方式一:当对对象的方法只调用一次时,可以用匿名对象来完成,这样写比较简化。

示例代码

import java.util.Random;
/*
需求:产生一个随机数并打印。
实现:使用Random的nextInt方法产生随机数。
*/
class Demo1
{

public static void main(String[] args)
{
/*
因为只需要产生一个随机数,Random的nextInt方法只需要调用一次
所以使用匿名对象的方式来调用。
*/
int a = new Random().nextInt();
System.out.println(a);
}

}


使用方式二:可以将匿名对象作为实际参数进行传递。从而可以不用在方法中创建变量,提高了编程效率,减少

了代码书写。但是这个对象实体在方法结束后,垃圾回收机制会将其作为垃圾回收。而非匿名对象则不同,当不使用了,会在某一时刻被回收,或是随着主函数的结束而被回收。

1.3、封装

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

好处:

(1).将变化隔离。

(2).便于使用。

(3).提高重用性。

(4).提高安全性。

封装原则:

(1).将不需要对外提供的内容都隐藏起来。
(2).把属性都隐藏,提供公共方法对其访问。

private(私有)关键字

(1).是一个权限修饰符。
(2).用于修饰成员(成员变量和成员函数)。
(3).被私有化的成员只在本类中有效。

注意:私有仅仅是封装的一种表现形式。

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

示例:

class Student
{
private String name;
private int age;
//对外提供get、set方法对私有化的成员进行访问。
public void setAge(int age)
{
this.age = age;
}
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public static void main(String[] args)
{
Student s = new Student();
//s.age=22; -------这是错误的,私有的成员变量不能这么访问。
s.setAge(22);
s.setName("zhangsan");
System.out.println("name="+s.getName()+"---age="+s.getAge());
}
}


1.4、构造函数

构造函数(Constructor)是一个特殊的函数。

特点:

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

(2).不用定义返回值类型。注意:没有返回值类型不等同于void,void也是一种返回值类型。

(3).不可以写return语句。

例如:public Student(参数列表){。。。}

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

注意:当一个类中没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数。如果自己定义了构

造函数,默认构造函数就没了。

构造函数的重载

构造函数的重载和普通函数相同,函数名相同,参数列表不同即可。

构造函数的访问权限

在定义构造函数时,如无特殊需要,应使用public关键字修饰构造函数。在一些特定情况下,我们不想让别人创

建该类对象,那么可以使用private修饰构造函数,例如单态设计模式。

构造函数和一般函数运行上的不同

构造函数是在对象一建立时就运行,是给对象初始化。而一般函数是被对象调用才执行,是给对象添加对象所具

备的功能。

还有构造函数只在对象建立时运行一次。而一般方法可以被该对象多次调用。
构造代码块:包含在一对大括号之间,给对象初始化。对象一建立就运行,并且优先于构造函数执行。

构造代码块和构造函数的区别:

(1).构造代码块是给所有对象进行统一初始化,
(2).而构造函数是给对应的对象初始化。
(3).构造代码快中定义的是不同对象共性的初始化内容。

1.5、this关键字

特点:this代表其所在函数所属对象的引用。

简单说:哪个对象在调用this所在的函数,this就代表哪个对象。

示例:

class Student
{
int age;
String name;
public Student(String name){
/*
this:一个作用是区分成员变量和局部变量。
另一个作用是代表对象的引用,如s1调用我,
this就是s1对象的引用。
this.name=name 就把张三赋值给s1的name
*/
this.name = name;
}
public static void main(String[] args)
{
Student s1 = new Student("张三");
}
}


this的应用:当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。但凡本

类功能内部使用了本类对象,都用this表示

this关键字在构造函数间调用

class Student
{
int age;
String name;
public Student(String name){
this.name = name;
}
public Student(String name,int age){
/*
调用本类中已经定义的构造函数
只能定义在构造函数的第一行。因为初始化要先执行。
*/
this(name);
this.age = age;
}
public static void main(String[] args)
{
Student s = new Student("张三",22);
System.out.println("name="+s.name+"--age="+s.age);
}
}

1.6、static(静态)关键字

static关键字用来修饰类的成员,被这个关键字修饰的成员都和类加载有关。

JVM运行时不会将所有类加载到内存,因为无法确定程序中要使用哪些。类在第一次使用时加载,只加载一次。

static特点:

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

(2).优先于的对象存在。明确一点:静态是先存在。对象是后存在的。

(3).被所有对象所共享

(4).可以直接被类名所调用。

静态变量:用static修饰的变量就是静态变量。

特点:

(1).静态变量在类加载后就初始化。

(2).静态变量被类的所有实例所共享。

(3).静态变量可以使用类名.变量名形式访问。

什么时候用?

如果在定义一个类的时候,发现一个成员变量需要被所有实例所共享,那么这个成员变量就需要定义为static

的。

静态方法:用static修饰的方法就是静态方法。

特点:
(1).静态方法在类加载后就可以使用。

(2).静态方法可以使用类名.方法名
形式访问。

(3).静态方法不能直接访问外部非静态成员。

因为外部非静态成员必须在类创建对象之后才能使用,而静态方法可以在没创建对象时就使用。

(4).静态方法中不能使用this、super关键字。

因为静态优先于对象存在。所以静态方法中不可以出现this、super。

什么时候用?

如果一个方法不用访问对象的非静态成员,那么就可以定义为静态的,这样使用者就不需要创建对象,直接

用类名调用。

实例变量(成员变量)和类变量(静态的成员变量)的区别:
(1).存放位置:

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

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

(2).生命周期:

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

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

静态利弊:



(1).对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。

(1).可以直接被类名调用。

弊:

(1).生命周期过长。

(2).访问出现局限性。(只能访问静态)。

静态的应用--工具类

静态方法通常是作为工具方法或者一个可以产生对象的方法被声明,目的是为了让调用者更方便的使用,不必创

建对象。

每一个应用程序中都有共性的功能,可以将这些功能进行抽取,独立封装。以便复用。看下面示例代码:

/*
需求:定义一些函数来操作数组。提高代码复用性。
函数都用static,方便调用
*/
public class ArrayTool
{
//获取int数组中的最大值。
public static int getMax(int[] arr)
{
int max = 0;
for(int x=1; x<arr.length; x++)
{
if(arr[x]>arr[max])
max = x;
}
return arr[max];
}

//获取int数组中的最小值。
public static int getMin(int[] arr)
{
int min = 0;
for(int x=1; x<arr.length; x++)
{
if(arr[x]<arr[min])
min = x;
}
return arr[min];
}
//选择排序。排序结果是从下到大
public static void selectSort(int[] arr)
{
for (int x=0; x<arr.length-1 ; x++ )
{
for(int y=x+1; y<arr.length; y++)
{
if(arr[x]>arr[y])
{
swap(arr,x,y);
}
}
}
}
//冒泡排序。排序结果是从下到大。
public static void bubbleSort(int[] arr)
{
for (int x=0; x<arr.length-1 ; x++ )
{
for(int y=0; y<arr.length-x-1; y++)
{
if(arr[y]>arr[y+1])
{
swap(arr,y,y+1);
}
}
}
}
//交换数组中两个元素的位置。
private  static void swap(int[] arr,int a,int b)
{
int temp = arr[a];
arr[a] = arr;
arr[b] = temp;
}
//用于打印数组中的元素
public static void printArray(int[] arr)
{
System.out.print("[");
for(int x=0; x<arr.length; x++)
{
if(x!=arr.length-1)
System.out.print(arr[x]+", ");
else
System.out.println(arr[x]+"]");
}
}
}


有了这么个类我们操作数组就方便多了。look下面。

/*
使用ArrayTool这个类的相关函数来操作数组。
*/
class ArrayToolDemo
{
public static void main(String[] args)
{
int[] arr1 = {11,1,33,32,6};
//获取数组最大值
int max = ArrayTool.getMax(arr1);
System.out.println("max="+max);
//获取数组最小值
int min = ArrayTool.getMin(arr1);
System.out.println("min="+min);
//打印数组
ArrayTool.printArray(arr1);

}
}


静态代码块

[b]格式:


static

{

静态代码块中的执行语句。

}

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

class StaticCode
{
static
{
System.out.println("执行静态代码块A");
}
}
class StaticCodeDemo
{
static
{
System.out.println("执行静态代码块B");
}
public static void main(String[] args)
{
new StaticCode();
new StaticCode();
}
static
{
System.out.println("执行静态代码块C");
}
}


执行结果:



先打印B、C说明:是优先于主函数执行。

A只打印一次:说明随着类的加载而执行,只执行一次。

1.7、 主函数

主函数:是一个特殊的函数。作为程序的入口,可以被jvm调用。

主函数的定义

public:代表着该函数访问权限是最大的。

static:代表主函数随着类的加载就已经存在了。

void:主函数没有具体的返回值。

main:不是关键字,但是是一个特殊的单词,可以被jvm识别。

String[] arr:函数的参数,参数类型是一个数组,该数组中的元素是字符串。字符串类型的数组。

主函数是固定格式的:被jvm识别。
jvm在调用主函数时,传入的是new String[0];

1.8、帮助文档制作--javadoc

帮助文档说直白点就是说明书。
java的说明书通过文档注释来完成。看示例代码。

/**
这是一个可以对数组进行操作的工具类,该类中提供了获取最值、排序等功能。
@author MT2
@version V1.1

*/

public class ArrayTool
{
/**
空参数构造函数。
*/
private ArrayTool(){}

/**
获取一个整形数组中的最大值。
@param arr 接收一个int类型的数组。
@return 会返回一个该数组中最大值。
*/
public static int getMax(int[] arr)
{
int max = 0;
for(int x=1; x<arr.length; x++)
{
if(arr[x]>arr[max])
max = x;
}
return arr[max];
}

/**
获取一个整形数组中的最小值。
@param arr 接收一个int类型的数组。
@return 会返回一个该数组中最小值。
*/
public static int getMin(int[] arr)
{
int min = 0;
for(int x=1; x<arr.length; x++)
{
if(arr[x]<arr[min])
min = x;
}
return arr[min];
}
/**
给int数组进行选择排序。
@param arr 接收一个int类型的数组。
*/
public static void selectSort(int[] arr)
{
for (int x=0; x<arr.length-1 ; x++ )
{
for(int y=x+1; y<arr.length; y++)
{
if(arr[x]>arr[y])
{
swap(arr,x,y);
}
}
}
}
/**
给int数组进行冒泡排序。
@param arr 接收一个int类型的数组。
*/
public static void bubbleSort(int[] arr)
{
for (int x=0; x<arr.length-1 ; x++ )
{
for(int y=0; y<arr.length-x-1; y++)
{
if(arr[y]>arr[y+1])
{
swap(arr,y,y+1);
}
}
}
}
/**
给数组中元素进行位置的置换。
@param arr  接收一个int类型的数组。
@param a 要置换的位置
@param b 要置换的位置
*/
private  static void swap(int[] arr,int a,int b)
{
int temp = arr[a];
arr[a] = arr;
arr[b] = temp;
}
/**
用于打印数组中的元素。打印形式是:[elemet1, element2, ...]
*/
public static void printArray(int[] arr)
{
System.out.print("[");
for(int x=0; x<arr.length; x++)
{
if(x!=arr.length-1)
System.out.print(arr[x]+", ");
else
System.out.println(arr[x]+"]");
}
}
}


通过javadoc工具提取文档注释。生成文档说明书。

打开DOS命令行,输入命令:javadoc -d helpdoc -author -version ArrayTool.java

-d:指定生成的文档保存路径。

-author:指定作者。

-version:指定版本。

看到如下信息文档制作就完成了。



生成的文档时网页形式的,效果如下。



[b]1.9、对象初始化过程

执行
Student s = new Student("MT2",20);过程:

(1).因为new用到了Person.class.所以会先找到Person.class文件并加载到内存中。

(2).执行该类中的static代码块,如果有的话,给Person.class类进行初始化。

(3).在堆内存中开辟空间,分配内存地址。

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

(5).对属性进行显示初始化。

(6).对对象进行构造代码块初始化。

(7).对对象进行对应的构造函数初始化。

(8).将内存地址付给栈内存中的p变量。

二、设计模式

为了完成某种特定需求儿经过大量理论总结和实践验证之后优选出的代码结构、编程风格、以及解决问题的思考

方式,这就是设计模式(Design pattern)。

23种设计模式——单例设计模式:解决一个类在内存只存在一个对象。

怎么保证对象唯一:

(1).为了避免其他程序过多建立该类对象。先禁止其他程序建立该类对象

(2).还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。

(3).为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。

用代码实现:
(1).将构造函数私有化。
(2).在类中创建一个本类对象。
(3).提供一个方法可以获取到该对象。
示例代码:

class Single
{

private  Single(){}

private static Single s = new Single();

public static  Single getInstance()
{
return s;
}
}


验证对象唯一

class SingleDemo
{
public static void main(String[] args)
{
Single s1 = Single.getInstance();
Single s2 = Single.getInstance();
s1.setName("zhangsan");
/*
如果打印的是"zhangsan",说明s1、s2引用同一个对象。
如果打印的是null,说明s1、s2引用的不是同一个对象。
*/
System.out.println(s2.getName());
}
}


执行结果






上面的写法是先初始化对象。称为:饿汉式。

另一种方式———懒汉式:对象是方法被调用时,才初始化,也叫做对象的延迟加载。

class Single
{
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;
}
}


synchronized关键字在多线程时会详细介绍。这里使用是为了避免多人调用getInstance方法造成对象不唯一的

情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: