----------- android培训、java培训、java学习型技术博客、期待与您交流! -----------
/* 面向对象(上)
1、理解面向对象
面向对象概念
面向对象是相对面向过程而言,面向对象和面向过程都是一种思想。
定义一:面向对象方法是一种运用对象、类、封装、继承、多态和消息等概念来构造、测试、重构软件的方法。
定义二:面向对象方法是以认识论为基础,用对象来理解和分析问题空间,并设计和开发出由对象构成的软件
系统(解空间)的方法。由于问题空间和解空间都是由对象组成的,这样可以消除由于问题空间和求
解空间结构上的不一致带来的问题。简言之,面向对象就是面向事情本身,面向对象的分析过程就是
认识客观世界的过程。
面向过程强调的是功能行为(执行者)
面向对象是将将功能封装进对象,强调具备了功能的对象。(指挥者)
面向对象是基于面向过程的。
面向对象的特点
是一种符合人们思考习惯的思想
可以将复杂的事情简单化
将程序员从执行者转换成了指挥者
完成需求时:先要去找具有所需的功能的对象来用。如果该对象不存在,那么创建一个具有所需功能的对象。
这样简化开发并提高复用。
面向对象开发、设计、特征
开发的过程:其实就是不断的创建对象,使用对象,指挥对象做事情。
设计的过程:其实就是在管理和维护对象之间的关系。
面向对象的特征:封装(encapsulation)、继承(inheritance)、多态(polymorphism)
2、类与对象的关系
使用计算机语言就是不断的在描述现实生活中的事物。java中描述事物通过类的形式体现,类是一组相同属性行为
的对象的抽象。对象即是该类事物实实在在存在的个体。描述任意一类事物就是在描述他的属性和行为。
如何创建对象
java中通过new关键字来创建实体。实体其实就是用来封装具体数据用的。
Car c = new Car();
通过Car类创建了一个具体对象。该对象如何使用呢。为了方便使用该对象,就给对象起个名字c,
是Car类型的,而Car是一个类,所以c是类类型变量。类类型变量指向对象new Car()。
类的定义
生活中描述事物无非就是描述事物的属性和行为。
如:人有身高,体重等属性;有说话,打球等行为。
Person p = new Person(){
int age; //人具有年龄这个属性
public void run() {} //人具有跑这样的功能行为。
}
java中用类class来描述事物也是如此,定义类其实是在定义类中的成员(成员变量和成员函数)。
属性:对应类中的成员变量。
行为:对应类中的成员函数。
成员变量和局部变量的区别
作用范围
成员变量:定义在类中,作用于整个类。
局部变量:只在方法内有效。比如函数上的参数,函数中的变量,语句中的变量。
public void function(int x){ //x是参数列表上的局部变量。
int y = 0; //y是函数中的局部变量
for(int z=0; z<3; x++){ //z是语句中的变量
} //当循环语句结束时,z在内存中释放。当function函数执行完毕,x和y在内存中释放
}
存储情况
成员变量:存储在堆内存中,随着对象的存在而存在。当对象变成垃圾被回收时,对象中的成员变量消失。
局部变量:存储在栈内存中,当方法被调用,或者语句被执行的时候,才存在。方法运行完毕,或者语句
运行完毕时,当局部会被自动释放。所以成员变量也称之为实例(对象)变量.
初始化情况
成员变量:在堆内存中有默认初始化值。默认值为0或null。
局部变量:必须手动初始化(赋值)后,才可以被使用。
class Person {
int num; //成员变量,jvm虚拟机默认值为0
public void method(){
int age ;
age = 10; //局部变量,必须手动赋值。
System.out.println(age);
}
}
3、创建对象、使用对象
创建对象的步骤:
主函数进栈,给类类型变量c分配空间
在堆内存中开辟空间,分配内存地址
在堆内存中建立对象特有属性,并进行默认初始化
对属性进行显示初始化(对对象的属性手动赋值)
将内存地址赋给栈内存中的c变量(指向了该对象)
使用对象的方法:无论使用变量还是功能函数,都可以直接类名.调用。
Car.num(调用属性)
Car.run()(调用功能函数)
4、匿名对象
是对象的简化形式,是没有名字的对象.(只要是简化形式就有一定局限性)
可以使用匿名对象两种情况:
当对对象方法仅进行一次调用的时;
Person p = new Person(); //正常的使用方式:类名.调用
p.show();
p.print();
new Person().show(); //用匿名对象。new Person()就是匿名对象
new Person().print();
匿名对象可以作为实际参数进行传递。
method(new Person());//匿名对象作为参数传递
public static void method(Person p){
.......
}
匿名对象可以调用属性,但没有意义。因为在堆内存中,匿名对象建立后,没有有被引用成为了垃圾,被jvm回收。
5、封装
是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:
将变化隔离。
便于使用。
提高重用性。
提高安全性。把属性私有化,建立对象就不能访问,但是要对外提供访问属性的方法。
封装原则:
将不需要对外提供的内容都隐藏起来。
把属性都隐藏,提供公共方法对其访问。
6、构造函数
特点:
函数名与类名相同
不用定义返回值类型
不可以写return语句
作用:给对象进行初始化。
重载:构造函数的重载和普通函数相同,函数名相同,参数列表不同即可。
调用:构造函数在new关键字创建对象时调用。构造函数可以在该类其它构造函数的第一个语句通过this关键字调用。
注意:每个类都有构造函数,即使没有显式定义构造函数,也会生成一个默认无参的构造函数,其中没有任何内容。
这个自动生成的构造函数只在未定义任何构造函数时生成,如果定义了一个有参的构造函数,那么就不会生成。
访问权限:在定义构造函数时,如无特殊需要,应使用public关键字修饰构造函数。
在一些特定情况下,不想让别人创建该类对象,那么可以使用private修饰构造函数,例如单例设计模式。
7、关键字
private:是一个权限修饰符。用于修饰成员(成员变量和成员函数)。被私有化的成员只在本类中有效。
将成员变量私有化后,对外提供对应的set 、get方法对变量进行访问。提高对数据访问的安全性。
this:this代表函数所属对象的引用,也就是本类对象的引用。
当方法中局部变量和成员变量重名,我们想调用成员变量时就可以使用this.变量名形式访问成员变量。
在方法中要将调用该方法的对象作为参数传递给另一个方法时,可以将this作为实参传给该方法。
在内部类中访问外部类的成员时,需要使用外部类名.this.成员名形式访问。
static:static关键字用来修饰类的成员,被这个关键字修饰的成员都和类加载有关。
被修饰后的成员具备以下特点:
随着类的加载而加载;
优先于对象存在;
被所有对象所共享;
可以直接被类名.调用;
静态变量:用static修饰的变量就是静态变量。
静态变量在类加载后就初始化。
静态变量被类的所有实例共享。
静态变量可以使用:类名.变量名 形式访问。
定义类时,如果成员变量需要被所有实例所共享,那么这个成员变量就定义为static。
静态方法:用static修饰的方法就是静态方法。
静态方法在类加载后就可以使用。
静态方法可以使用 类名.方法名 形式访问。
静态方法不能直接访问外部非静态成员。
外部非静态成员必须在类创建对象之后才能使用,而静态方法可以不创建对象就使用。如果要在静态方法
内部访问外部非静态成员,需要先创建该类对象,通过对象访问。
静态方法中不能使用this关键字:因为this是个引用,哪个对象调用方法就引用哪个对象。
而静态方法有可能不是被对象调用的,this无从引用。
如果一个方法不用访问非静态成员,那么就定义为静态的,这样使用者就不需要创建对象,直接用类名调用。
静态方法通常是作为工具方法或者一个可以产生对象的方法被声明,是为了让调用者不必创建对象就可以使用。
静态代码块:用static修饰的代码块就是静态代码块。
静态代码块在类加载后执行。
静态代码块和静态方法相同,不能使用外部非静态成员。
静态代码块执行和静态变量的初始化顺序由代码从上到下顺序决定。
如果有一段代码想在使用某个类的时候就运行, 且只运行一次, 就可以写在静态代码块中.
静态内部类:用static修饰的内部类就是静态内部类。
静态内部类在类加载后就可以创建对象,无需创建外部类对象。
与内部类使用大致相同
8、代码块
局部代码块:
public void method() {
{
int x = 4;
System.out.println("x="+x);
}
}
作用:控制变量的生命周期。程序使用完x后,并且在下面的代码中也不会用到x,就没必要让x占用空间。这时可以
使用局部代码块,将x及其所涉及到的区域封装为局部代码块,在程序执行中顺序不变,执行完消失。
构造代码块:
class Demo {
{
System.out.println("构造代码块")
}
}
作用:给所有对象进行初始化,存在于类中。当类中的构造方法以重载的形式存在,且有共同成员变量或方法时,
可以通过构造代码块对其进行初始化;这样可以减少代码的重复;它是不能接收任何参数的
静态代码块:
static{
静态代码块中的执行语句
}
作用:给类进行初始化。当类中的方法都被静态化,并且构造方法被私有化了。这时我们无法再将这个类实例化,
但又需要让类增加一些属性,就可以使用静态代码块
静态代码块和构造代码块的区别:
相同点:都是在JVM加载类时,在构造方法执行之前执行,在类中都可以定义多个,对一些static变量进行赋值。
不同点:静态代码块在非静态代码块之前执行(静态代码块—>非静态代码块—>构造方法)。
静态代码块只在第一次new执行一次,之后不再执行,而构造代码块在每new一次就执行一次。
非静态代码块可在普通方法中定义(不过作用不大),而静态代码块不行。
9、单例设计模式:(Singleton Pattern)保证在整个程序中某个类只能存在一个对象,这个类不能再创建第二个对象。
步骤:
将构造函数私有化
在类中创建一个本类对象
提供一个方法可以获取到该对象
饿汉式:Single类一加载进内存,就创建好了对象;
class SingletonPattern {
private SingletonPattern() {}; //构造函数私有化;
private static SingletonPattern s = new SingletonPattern(); //创建本类对象实例;
public static SingletonPattern getInstance() { //对外提供获取本类对象实例的方法;
return s;
}
}
懒汉式:对象只有在调用获取对象的方法时才初始化,也叫做对象的延时加载;
class SingleLazy {
private SingleLazy() {};
private static SingleLazy si = null; //类加载进内存时先不创建对象;
public static SingleLazy getInstance() {
if (si == null) { //双重判断,提高效率
synchronized (SingleLazy.class) { //上锁,保证线程安全,
if (si == null)
si = new SingleLazy(); //满足判断条件,对象初始化;
}
}
return si;
}
}
10、方法区(数据共享区)
方法区是各个线程所共享的内存区域,它用于存储已被虚拟机加载的类信息.常量.静态变量.即时编译器编译后的代码
等数据.虽然java虚拟机把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该
是与Java堆区分开来。