-----------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.单列设计模式
设计模式:
解决某一类问题最行之有效的方法,Java中23种设计模式。
单例设计模式:解决一个类在内存中只存在一个对象
比如对于多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性。
想要保证对象唯一:
为了避免其他程序过多建立该类对象,先禁止其他程序建立该类对象;
还为了让其他程序可以访问到该类对象,只好在本类中自定义一个对象;
为了方便其他程序对自定义对象的访问, 可以对外提供一些访问方式;
单例设计模式之饿汉式
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;
}
为什么有饿汉式和有懒汉式呢?
原因是面试中会考到,因为面试考的都是懒汉式,懒汉式中会出现很多的安全隐患。这里面涵盖了很多的知识点。
实际开发中用饿汉式,因为在考虑多线程时会比较安全,懒汉式的存在安全问题,解决安全问题时,
双重判断,加入锁或同步代码块。
总结:
饿汉式:一开始对象就初始化。 因为饿汉式在考虑多线程时比较安全。较为浪费内存空间,但这是合理的浪费。
懒汉式:对象调用方法时,才初始化,也叫做对象的延时加载。 比较节省内存,因为只有调用才占内存。
养成良好的节约内存习惯固然好,但是我们在多线程开发的中,要选择饿汉式,较为安全。这种浪费资源是合理的。