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

时间:2023-02-18 17:04:23

      

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

面向对象的概念

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

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

 面向对象:将功能封装进对象。调用对象的功能。

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

面向对象的特点:

1.它符合现代人们的思考习惯

2.它让复杂的事情简单化 。

3.让我们从曾经的执行者变成现在的指挥者。

老师给我们给我们讲一个面向对象的的例子:

其实面试官您本身就在用面向对象的方式思考问题。因为面试官您的能力而言,来了一个软件项目的话。你从需求分析到设计在到开发测试都可以完成。但是这样特别耗费时间,您为了提高效率,就需要去找一些具备专业编程经验的人来完成这些项目。我这好就是那个具备专业编程经验的对象。你只要指挥我这个对象去做事情就可以了。我会给你发一个非常满意的结果。

至于构成您就不用管了。所以面试官您就是在用面向对象的方式思考问题,来提高效率。而我就是具备专业编程经验的人。

我自己总结的面向对象的小故事:

我想洗衣服,我可以自己洗。但是很浪费时间。我可以调用洗衣机的功能。去帮我完成洗衣服的这件事。我不需要知道他是怎么转动的,他的工作原理是什么,怎么供电怎样脱水等。洗完了我看到是干净的就行了。其他事情我不需要知道。我只要对应他的功能就行了。

面向对象三个特征:封装,继承,多态

以后开发过程中:其实就是找对象用。没有对象,就创建一个对象。

找对象,建对象,使用对象,并维护对象的关系。

类和对象的关系:

类:就是现实生活中的事物的描述。

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

描述:提取对象*性的内容,具体的抽象。

映射到java中的描述就是class定义类。

具体对象就是java在堆内存中用new建立实体。

属性对应的是类中的变量,行为对应的是类中的方式(方法)

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

类中不必有主函数,不必保证独立运行,只要有一个主函数调用就可以。

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

员变量和局部变量:

作用范围:

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

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

在内存中的位置:

成员变量:在堆内存中,因为对象的存在,才在内存中存在。

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

匿名对象:

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

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

1.当对象的方法只调用一次时,可以用匿名对象来完成。

这样写比较简单。如果一个对象对多个成员进行调用,必须给这个对象起个名字。

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

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

成员变量定义在类中,作用于整个类中。

局部变量定义在函数,语句,局部代码块中,只在所属的大括号区域内有效。

成员变量在堆内存的对象中。局部变量在栈内存的方法中。

成员变量随着对象的消失而消失。局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。

成员变量都有默认的初始值。局部变量没有默认的初始化值。

面向对象的封装

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

封装的好处:将变化隔离,便于使用。提高 复用性。

封装的原则:将不需要对外提供的内容都隐藏起来。

把属性都隐藏,提供公共的方法对其访问。

priavte:私有,权限修饰符。用于修饰类中的成员(成员变量,成员函数)。私有只在本类中有效。是最小的权限修饰符。

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

之所以对外提供访问方式,就是因为可以在访问方式这中加入逻辑判断等语句。

对方法的数据进行操作。提高代码的健壮性。

构造函数特点:

(1).函数名于类名相同。不用定义返回值类型。不可以写return语句。

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

对象一建立就会调用与之对应的构造函数。

构造函数的作用:可以给对象进行初始化。

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

当在类中自定义了构造函数后,默认的构造函数就没有了。

构造函数和一般函数在写法上有不同。

在运行上也有不同。

 构造函数是在对象一建立就运行,给对象初始化。

而一般的方法是对象调用才执行,是给对象添加对象具体功能。

构造函数是对象一建立,构造函数就只运行一次。

而一般方法是只能被对象 调用才执行,可以执行很多次。

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

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

当分析事物时,该事物存在具备一些特性或者行为,那么将这些内容定义在构造函数中。

构造代码块作用:给对象进行初始化的。

对象已建立就运行。而且优先于构造函数执行。

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

构造代码块是给所有的对象进行初始化。而构造函数是给对应对象进行初始化的。

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

this关键字

this:代表它所在函数所属对象的引用。

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

static关键字

static:是静态修饰符。用来修饰成员(成员函数,成员变量)

当成员被静态修饰后,就多了一个调用方式。出了可以被对象调用外。

还可以直接被类名调用。类名.静态成员。

static特点:随着类的加载而加载。也就是说:静态会随着类的消失而消失。

说明它的生命周期最长。优先于对象存在。(明确一点:静态是先存在的,对象是后存在的)

被所有对象所共享。

可以直接被类名调用,

实例变量和类变量的区别:

存放位置:

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

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

生命周期:

类变量什么周期最长。随着类的消失而消失。

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

静态使用注意事项:

静态方法只能访问静态成员。

非静态方法既可以访问静态的也可以访问非静态的。

静态成员中不可以定义this,super关键字。

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

静态有利有弊:

静态好处:对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象都存储一份。

可以直接被类名调用。

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

什么时候使用静态?

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

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

当对象中出现共享数据时,该数据被静态所修饰。

对象中的特有数据要定义成非静态存在于堆内存中。

什么时候定义静态函数?

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

静态的应用:

public class   ArrayTool
{
/**
空参数构造函数。
*/
private ArrayTool(){}
/**
获取一个整形数组中的最大值。
@param  arr 接收一个int类型的数组。
@return  会返回一个该数组中的最大值。
*/
public static intgetMax(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 bubblesor(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 voidswap(int[] arr,int a,int b)
{
int temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
/**
用于打印数组中的元素。
 @param  arr 接收一个int类对象型的数组。
打印形式是:[element1, 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]+"]");
}
}


}
/*
一个类中默认会有一个空参数的构造函数。
这个默认的构造函数的权限和所属类一致。
如果累被public修饰,那么默认的构造函数也带public修饰符。
如果累没有被public修饰,那么默认的构造函数,也没有public 修饰。


默认构造函数的权限是随着类的变化而变化的。
*/

1.单列设计模式

设计模式: 

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

单例设计模式:解决一个类在内存中只存在一个对象 

比如对于多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性。 

想要保证对象唯一: 

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

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

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

单例设计模式之饿汉式 

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

思路: 

将构造函数私有化; 

在类中创建一个本类对象; 

提供一个公共的访问方法,可以获取到该类对象; 

步骤: 

//将构造函数私有化

private Single(){} 

//在类中创建一个本类对象(final关键字是最终的意思final修饰的变量会成为全局常量)

private static  finla  Single  s  =new Single(); 

//提供一个公共的访问方法,可以获取到该类对象

public static Single getInstance(){ 

return s; 

单例设计模式之懒汉式 

对象是方法被调用时才初始化,也叫对象的延时加载 

Single类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象。 

步骤: 

private Single(){} 

private static Single single =null

public static Single getInstance()

if(single==null)

synchronized(Single.class)

if(single==null) 

single  s=new Single(); 

return s; 

为什么有饿汉式有懒汉式 

原因是面试中会考到,因为面试考的都是懒汉式,懒汉式中会出现很多的安全隐患。这里面涵盖了很多的知识点。

 

实际开发中用饿汉式,因为在考虑多线程时会比较安全,懒汉式的存在安全问题,解决安全问题时,

双重判断,加入锁或同步代码块 

总结: 

饿汉式:一开始对象初始化。 因为饿汉式在考虑多线程时比较安全。较为浪费内存空间,但这是合理的浪费。

懒汉式:对象调用方法时,才初始化,也叫做对象的延时加载。 比较节省内存,因为只有调用才占内存。

养成良好的节约内存习惯固然好但是我们在多线程开发的中,要选择饿汉式,较为安全。这种浪费资源是合理的。