黑马程序员---面向对象

                      -----------android培训java培训、java学习型技术博客、期待与您交流!---------


面向对象

             

       理解面向对象

 

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

 

                          面向过程:强调的是行为功能

 

                          面向对象:将功能封装进对象,强调具备了功能的对象。

 

                           面向对象是基于面向的过程。

 

              面向对象的出现,让曾经在过程中的执行者,变成了对象中的指挥者。
      

              面向过程和面向对象可以用到现实中来比喻:

 

                     如:把大象装进冰箱需要几步。

 

                             面向过程(打开冰箱,冰箱存储,冰箱关闭)

 

                             面向对象(冰箱打开,冰箱存储,冰箱关闭)

 

              面试题:你怎么理解面向对象的?

 

                               先要说面向对象的特点:面向对象是一种思想,能将复杂的事情简单化,能让我们的角色转变。

 

                               再结合实际场景说明:其实面试官你本身就在用面向对象的思想思考问题,

 

                                      我就是对象,我具备专业编程的能力,

 

                                      而公司需要有编程能力的对象,您可以指挥我做事情,

 

                                      我可以给您一个满意的结果,而且您不用去管中间的过程。

 

                                      所以面试官您就在用面向对象的方式思考问题,来提高公司的效率,

 

                                      而我就是具备专业编程经验的人。而且我也相信我会用我的编程能力为公司创造价值

 

       面向对象的三个特征:

 

              封装,继承,多态。

 

              以后的开发过程,其实就是找对象使用,没有对象就创建一个对象。总结就是找对象,建立对象,使用对象,维护对象的关系。

 

       写程序时不限定义功能,要先面向对象,

 

       对象需要什么功能就写进去,这个叫做封装。

 

类和对象

     

       类和对象的关系

 

              类就是对现实生活中事物的被描述;

 

              对象就是这类事物实实在在的个体。

 

       想要描述:提取对象中共性内容,对具体地抽象。

 

       描述时: 这些对象的共性有,如:姓名,年龄.....

 

       映射到Java

 

              描述就是class文件的类,具体对象就是对应Java在堆内存中用new简历实体

 

             例:图纸和小汽车的关系就是类与对象的关系。

 

                     可以理解为:图纸就是类,汽车就是堆内存中的对象。

 

                     类与对象的关系如图:


 

       描述事物分为两个部分:

 

              1. 事物的属性。2. 事物的行为(功能)。

 

              在小汽车的例子中小汽车的属性就是车的颜色,轮胎数。

 

              小汽车的行为(功能)可以在路上跑。

 

       属性对应的就是变量,行为对应的就是类中的函数(方法)。

 

       其实定义类就是在描述事物,就是在定义属性和行为,属性和行为共同称为类中的成员(成员变量和成员方法)

 

       类只为了描述事物,不要求独立运行时可不加主函数

 

       生产汽车(建立对象),在Java中通过new操作符来完成,其实就是在堆内存中产生一个实体。

 

       建立对象格式:类名  引用型数据变量 = new 类名()

 

       注:引用型数据变量指向对象。

 

       指挥对象做事,在Java中的指挥方式是:对象.对象成员

 

       new来建立对象:

 

              就是把现实生活中的对象在堆内存中产生,

 

       对象的特点:

 

              在于封装数据,数据包括:属性,行为。

 

       注:操作对象中的内容要指挥对象,指挥哪个对象要明确,操作对象中的哪个成员要明确。

 

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

 

              1.  作用范围

 

                   成员变量作用于整个类中,

 

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

 

              2.  在内存中的位置

 

                    成员变量在堆内存中,

 

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

 

              3.  存在周期

 

                    成员变量随着对象的创建而创建,随着对象的消失而消失。

 

                    局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。

 

              4.  初始化值

 

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

 

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

 

匿名对象

 

       匿名对象是对象的简化形式:new类名 ();

 

       匿名对象的两种使用情况:

 

              1.  当对象仅进行一次调用时,可转化成匿名对象,

 

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

 

       注:调用匿名对象的属性是没有意义。

 

封装(Encapsulation


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

 

       封装好处:

 

              1.  将变化隔离。

 

              2.  便于使用。

 

              3.  提高重用性。

 

              4.  提高安全性。

 

       封装原则:

 

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

 

       private 关键字:私有权限修饰符

 

              用于修饰类中的成员(成员变量,成员函数)。

 

              被私有化的成员只有在本类中有效(在其他类中不可以访问)。

 

             注:私有仅是封装的一种体现

 

       例:对Person类中age进行私有化,并对外界提供公共的访问方式。

 

             代码示例

/*
封装练习

对Person类中age进行私有化,并对外界提供公共的访问方式。
*/
//创建Person类
class Person
{
	//定义私有的年龄属性
	private int age;

	//对外提供公共的设置年龄的方法
	public void setAge(int x)
	{
		//加入判断,使程序更加严谨
		if(x>=0 && x<=100)
			//如果用户设置的年龄符合上述条件,那么就把参数传入的值赋给age
			age = x;
		//否则就是用户传入的数不对
		else
			System.out.println("传入的年龄有误");
	}

	//对外界提供公共的获取年龄的方法
	public int getAge()
	{
		return age;
	}
	
	//定义说话方法,让人说出自己的年龄
	public void speak()
	{
		System.out.println("我的年龄:"+age);
	}
}

class  PersonDemo1
{
	public static void main(String[] args) 
	{
		//建立person类对象
		Person p = new Person();

		//年龄是私有的,要用提供的设置方法设置
		p.setAge(12);
		//年龄还可以通过公有的获取方法获取
		System.out.println("年龄:"+p.getAge());

		//最后调用person类中的speak方法,输出结果
		p.speak();
	}
}

                                    运行结果



 

 

              将age私有化以后,类以外即使建立了对象也不能直接访问,但是人应该有年龄,就需要在Person类中对应访问age的方式,

 

              对外供应set get方法对其进行访问,提高数据访问的安全性。

 

              之所以对外提供访问方式,是因为可以在访问方式中加入逻辑判断等语句, 对访问的数据进行操作没提高代码的健壮性。

 

构造函数

   

       构造函数:创建对象时调用的函数

 

       构造函数的特点:

 

              1.  函数名与类名相同。

 

              2.  不定义返回值类型。

 

              3.  不可以写return语句。

 

       构造函数的作用:给对象初始化。

 

       小细节:当一个类中没有定义构造函数时,系统会默认给该类加入一个空参数的构造函数,当类中定义了构造函数后,默认的构造函数就没有了。

 

       创建对象都必须要经过构造函数初始化。

 

              注意:1.  默认构造函数的特点。

 

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

 

       构造函数的重载

 

              分别定义不同的构造函数对不同的对象进行初始化。

 

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

 

              1.  构造函数:在对象一建立就会运行,给对象初始化

 

                   一般函数:是对象建立后需要函数功能时才调用(函数只有被调用才执行)

 

              .2.  构造函数:在对象建立时只调用一次。

 

                    一般函数:在对象建立后只要需要函数的功能,可以被调用多次。

 

       什么时候定义构造函数呢?

 

              当分析事物时,该事物存在就具备一些特性或者行为,那么将这些内容定义在构造函数中,需要未知内容参与运算的话就定义参数。

 

       构造函数内存图解


 

 

       构造代码块

 

              作用:给对象进行初始化,对象一建立就运行,

 

                          而且优先于构造函数执行。

 

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

 

                     构造代码块是给所有对象进行统一初始化的。

 

                     而构造函数是给对应的对象进行初始化的。

 

              把不同对象的共性初始化的方式定义在构造代码块中就能初始化所有对象。

 

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

 

       this关键字

 

              this关键字用于区别局部变量和成员变量同名的情况,其实是用作代表对象的。

 

              this就代表本类对象,代表它所在函数所属对象的引用。

 

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

 

              this应用

 

                     当定义类中函数时,该函数内部要用到调用该函数的对象时,

 

                     就用this表示这个对象,但凡本类功能内部使用到了本类对象都用this表示。

 

              看到this想到这是一个对象的引用,哪个对象调用方法this就代表哪个对象。 

     

              this语句

 

                     用于构造函数之间互相调用。如:this(name);

 

              注:this只能定义在构造函数的第一行。因为初始化要先执行。

 

                     一般函数不能直接调用构造函数,因为this语句不能用在一般函数中,只能用在构造函数中。      

 

              this代码演示

 

/*
this代码演示

还是创建Person类
*/
//定义Person类
class Person
{
	//定义姓名和年龄属性
	private String name;
	private int age;

	//定义构造函数,用this代表对象
	//只初始化姓名的构造函数
	Person(String name)
	{
		this.name = name;
	}
	//初始化姓名和年龄的构造函数
	Person(String name , int age)
	{
		this.name = name;
		this.age = age;
	}
	//定义说话功能
	public void speak()
	{
		System.out.println("name:"+name+"....age:"+age);
		show();
	}
	public void show()
	{
		System.out.println(this.name);
	}
}

class  ThisDemo
{
	public static void main(String[] args) 
	{
		//使用不同的构造方法定义对象,也就是传入的参数不同
		//只有姓名的对象
		Person p1 = new Person("张三");

		//姓名和年龄都有的对象
		Person p2 = new Person("李四",45);

		//调用Speak方法,输出对象
		p1.speak();
		p2.speak();
	}
}

                        运行结果



             

   

 static(静态关键字)

 

    用于修饰成员(成员变量和成员函数),

 

       被修饰后的成员具备以下特点

 

              1.   随着类名的加载而加载。

 

              2.   优先于对象存在。

 

              3.   被所有对象共享。

 

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

 

       static特点解释

 

              1.   类被使用时要进入内存,当类加载到内存中时,static修饰的成员就已经在内存中开辟了空间

 

                   (随着类的消失而消失,只要类存在就存在)静态会随着类的消失而消失,说明它的生命周期最长。

 

                   (不建议定太多静态成员,在定义前要分析成员是不是被多个对象共享)

 

              2.   明确静态是先存在的,对象时后存在的。

 

       实例变量(成员变量)和类变量(静态变量)的区别

 

              1.   存放位置

 

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

 

                     实例变量随着对象的简历存在于堆内存中。

 

              2.   生命周期

 

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

 

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

 

       什么时候使用静态呢?

 

              要从两方面下手,因为静态修饰的内容有成员变量和函数。

 

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

 

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

 

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

 

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

 

       静态的使用注意

 

              1.   静态方法只能访问静态成员,非静态方法即可访问静态成员也可访问非静态成员。

 

              2.   静态方法中不可以写thissuper关键字,因为静态优先于对象存在,所以静态方法中不能出现this

 

              3.   主函数是静态的。

 

      静态有利有弊

 

           好处:对对象的共享数句进行单独空间的存储,

 

                      节省空间,没有必要每个对象都存储一份,

 

                       可以直接被类名调用。(一般情况下想要调用类中的成员,需要建立一个类的对象去调用类中的方法)

 

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

 

      理解:每个对象都有的成员就要共享,每个对象特有的成员就不要共享,特有内容就随着对象而存储。


                 就像人出生都会哭就是都有的共性,所以需要共享,而每个人的名字又不同,所以名字就不要共享。

 

      主函数

 

           public static void main(String[ ]args)

 

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

 

           主函数中关键字的定义

 

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

 

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

 

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

 

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

 

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

 

           主函数是固定格式的:Jvm识别

 

           Jvm在调用主函数时,传入的是new String[0]

 

           Java进行调用时就给主函数的数组进行存入值。

 

      静态的应用

 

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

         

           当编译一个文件时用到其他类时,编译器会在指定目录下(无指定目录就在当前目录下)寻找有没有程序适用的其他类的文件。

 

           下面我们来做一个练习:建立一个ArrayTool类这个类包括了得到数组中的最大值最小值,和数组的排序。

 

                 问题

 

                      1.   对象是用于封装数据的,可是ArrayTool对象并未封装特有数据。

 

                      2.   操作数组的每一个方法都没有用到ArrayTool对象中的特有数据,

 

                            这时就考虑让程序更严谨,不需要对象,可以将ArrayTool中的方法都定义为静态的。


                            直接用类名调用即可(通常工具类里定义的都是静态方法)

 

                 将方法都静态后,可以方便调用,但是该类还是可以被其他程序建立对象的,

 

                 为了更为严谨,强制让该类不能建立对象,可以将构造函数私有化完成来达到让该类不能创建对象的目的。

 

                 接下来就可以使用该工具类,但是很遗憾该类中到底定义了多少个方法,

 

                 用户不清楚,所以我们要制作一个类的说明书,让使用者可以更加方便直接的使用该类。


                 注意:想要生成文档类前面必须加public修饰符,不修饰权限就不够大,可能在某个范围之内没暴露出去,视为被封装

                             

                             不一定私有才封装。文档中体现的是准备暴露的内容


                 小知识点:一个类中当没有定义构造函数时,会有一个默认的空参数的构造函数(系统自动加上的),


                                     这个默认的构造函数的权限和所属的类一致,如果类被public修饰,那么默认的构造函数也被public修饰。


                                     如果类没被public修饰,那么默认的构造函数也没有被public修饰。


                                     默认的构造函数的全显示随着类的权限的变化而变化的


                 下面我们来制作ArrayTool类,并把说明文字加入其中。

/**
这是一个可以对数组进行操作的工具类
类中提供了,获取最大值最小值,选择排序,冒泡排序功能。
@author 张三
@version 1.5

*/

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[b];
		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]+"]");
		}
	}
}
 

                     现在咱们要来建立ArrayTool的使用说明

 

                                    dos命令行中输入命令:javadoc -d Myhelp -author-version ArrayTool.java

 

                                    Java中的javadoc工具就会帮我们完成说明文档也称API的制作。

 

                    

 

                这就是我们自己制作的ArrayTool“说明文件

 

      

 

              注:如:class Demo

                            {

                                   Demo(){};                           //这不是默认函数,默认函数是看不见的,


                                   //这是空参数构造函数,写上就没有默认构造函数了              

                            }


       静态代码块


                格式:


                          static {


                                     静态代码块中要执行的语句;

                          }


                特点:随着类的加载而执行,只执行一次,用于给类进行初始化用的,并优先于主函数执行。静态代码块不能调用非静态成员。

 

       对象的初始化过程

 

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

 

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

 

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

 

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

 

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

 

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

 

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

 

              8.   将内存地址赋给栈内存中的变量。

 

单例设计模式

 

    设计模式是解决某一类问题最行之有效的方法。

 

       而单例设计模式解决的是一个类在内存中只存在一个对象的需求。

 

       想要保证对象的唯一

 

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

 

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

 

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

 

       用代码实现单例设计模式需要三个步骤

 

              1.   将构造函数私有化

 

                     private.构造函数

 

              2.   在类中创建一个本类对象

 

                    private static类名 s = new类名();        

 

              3.   提供一个访问方法可以获取到该对象

 

                    public   static  类名 函数名()                 //被类名调用必须要静态

                    {

      

                            return   s;

 

                    }

 

              单例设计模式只是为了保证内存中的对象唯一,类中其他属性该怎么描述吗,还是怎么描述。

 

              当需要该事物的对象保证在内存中唯一时,就将以上散三步的代码加上即可     

 

       单例设计模式有两种写法

 

              1.   饿汉式

 

                     也就是刚三部中的示例语句。它的特点是先初始化对象。

 

                     如:Single类一进内存,就已经创建好了对象。

 

                     在实际开发中,出于安全考虑,建议使用饿汉式。

 

    class Single  
    {  
         private static Single s=new Single();  
         private Single(){}  
         public static Single getInstance()  
         {  
              return s;  
         }  
    }  

 

              2.   懒汉式

 

                     它的特点:对象是方法被调用时,才初始化,这也叫对象的延时加载。

 

                     如:在以下完整代码中,Single类进内存,对象还没有存在,

 

                     只有调用了getInstance()方法时,才创建对象。

      

                     在面试中最常用到懒汉式

class Single  
{  
     private static Single s=null;  
     private Single(){}  
     public static Single getInstance()  
     {  
          if(s==null)   
               s=new Single();  
          return s;  
     }  

 

       个人理解:饿汉式和懒汉式的作用都是让类只能被创建一个对象。饿汉式是先创建对象,等方法被调用才返回对象的引用。


                           而懒汉式,是等方法被调用时,才创建对象,并返回对象的引用。

      

 

       总结:开发一般都用饿汉式,简单安全,可以解决我们还没有学到的多线程问题

 

                    而懒汉式是在面试中运用的比较多,因为是延时加载,只有调用才占内存。

 

                    所以:定义单例时建议使用饿汉式,懒汉式也要掌握。

 



谢谢大家的观看~!

                     -----------android 培训 java培训 、java学习型技术博客、期待与您交流!---------
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值