黑马程序员-->Java基础-->面向对象

来源:互联网 发布:北京赛车开奖数据接口 编辑:程序博客网 时间:2024/05/18 00:47

-------android培训java培训、期待与您交流! ----------

一、概述

(1)面向对象是相对面向过程而言,面向过程强调的是功能行为,面向对象是将功能封装进对象,强调具备了功能的对象,两者都是解决问题的一种思想。面向对象可以让复杂的问题简单化,角色发生转变,从执行者变为指挥者。
(2)面向对象和面向过程的区别,举例说明一下。
 
面向过程:面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
 
面向对象:面向对象是把构成问题的事物分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。
 
举例:我要用电脑看电影!这台电脑就是一个对象,它具备有视频功能,所以我现在就在使用这个电脑对象的视频功能。这时候就是运用到了面向对象的思想,将原本的问题简单化。
 
(3)面向对象的特点:封装,继承,多态。
以后开发:其实就是找对象使用,没有对象就创建一个对象。
简单的说:找对象,建立对象,使用对象,维护对象的关系

(4)类和对象的关系:
类:对现实生活中事物的描述。描述事物其实就是在描述事物的属性和行为。属性对应类中的变量,行为对应类中的函数。
对象:就是这类事物,实实在在存在的个体。

(5)局部变量和成员变量的区别:
作用范围:成员变量作用于整个类中。局部变量作用域函数或者语句中。
 
在内存中的位置:成员变量在堆内存中,因为对象的存在,才在内存中存在(即随着对象的产生而存在,消失而消失),而局部变量存在于栈内存中,随着所属区域的运行而存在,结束而释放。
 
(6)匿名对象
匿名对象:是对象的简化形式。

匿名对象使用方式一:当对对象方法只调用一次时,可以用匿名对象来完成,这样写比较简化。如果对一个对象进行多个成员的调用,必须给这个对象起个名字。
 
匿名对象使用方式二:可以将匿名对象作为实际参数进行传递。
 
二、封装
1、封装:指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

   好处:将变化隔离,便于使用,提高重用性,提高安全性。

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

   科普:函数是最小的封装体。

   private关键字:私有,权限修饰符,用于修饰类中的成员(成员变量和成员函数)。被私有化的成员只在本类中有效。

   常用方式之一:将成员变量私有化,对外提供对应的set和get方法对其进行访问,提高对数据访问的安全性。私有仅仅是封装的一种表现形式。之所以对外提供访问方式,就是因为可以在访问方式中加入逻辑判断等语句,对访问的数据进行操作。提高代码的健壮性。

2、构造函数
 
格式:person(){ }
 
特点:函数名与类名相同,不用定义返回值类型,该函数没有具体的返回值,即不可以写return语句。多个构造函数是以重载的形式存在的。
 
作用:用于给对象进行初始化,对象一建立就会调用与之对应的构造函数。
 
默认构造函数的特点:当一个函数中没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数。当在类中自定义了构造函数后,默认的构造函数就没有了。
 
知识点:构造函数和一般函数的区别:
 
a.两个函数定义格式不同,即在写法上不一样;
 
b.构造函数是在对象一建立就运行,给对象进行初始化;而一般函数是对象调用才执行,给对象添加对象具备的功能。一个对象建立,构造函数只运行一次,而一般方法是可以被对象调用多次。

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

3、构造代码块
 
格式:{ System.out.println("hello word")};
 
作用:给对象进行初始化。对象一建立就运行,而且优先于构造函数执行。
 
构造函数和构造代码块的区别:构造函数是给对应的对象进行初始化,而构造代码块是给所有的对象进行统一初始化。
应用:构造代码块中定义的是不同对象共性的初始化内容。
 
4、关键字this
this适用于区分局部变量和成员变量同名情况。

this关键字:代表本类的对象,也就是代表它所在函数所属对象的引用。简单的说:哪个对象在调用this所在函数,this就代表那个对象。

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

this语句用于构造函数之间进行相互调用,并且this语句只能定义在构造函数的第一行,因为初始化动作要先执行。
注意: this不能用在static静态方法中。

5、关键字static
static是一个修饰符,用于修改成员变量和成员函数。当成员被静态修饰后,就多了一种调用方式,除了可以被对象调用外,还可以被类名调用。格式: 类名.静态成员
 
static修饰成员变量,代码上无变化,但内存上有区别,static将变量封装进方法区,实现共享节省了内存。
 
static的特点:
a.随着类的加载而加载;也就是说:静态会随着类的消失而消失,说明它的生命周期最长。
 
b.优先于对象存在。明确一点:静态是先存在,对象是后存在的。
 
c.被所有对象所共享。
 
d.可以直接被类名所调用。
 
实例变量(成员变量)和类变量(静态的成员变量)的区别:
a.类变量随着类的加载而存在于方法区中,实例变量随着对象的建立而存在于堆内存中;
 
b.类变量的生命周期最长,随着类的消失而消失,实例变量的生命周期随着对象的消失而消失;
 
静态使用注意事项:
a.静态方法只能访问静态的成员,非静态方法既可以访问静态也可以访问非静态。
 
b.静态方法中不可以定义this,super关键字,因为静态有优先于对象存在,所以静态方法中不可以出现this;
 
静态的利弊:
利:对对象的共享数据进行单独空间的存储,节省空间,没有必要每一个对象中都存储一份,可以直接被类名调用;
 
弊:生命周期长,访问出现局限性(只能访问静态)。

什么时候使用静态,需要从静态变量和静态函数两方面考虑。
1、什么时候定义静态变量(类变量)?
当对象中出现共享数据时,该数据被静态所修饰,对象中的特有数据要定义成非静态存在于堆内存中。
2、什么时候定义静态函数?
当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定义成静态的。

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

主函数的定义:

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

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

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

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

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

主函数是固定格式的,为JVM识别。

6、静态代码块
格式:
static {静态代码块中的执行语句}
 
特点:随着类的加载而执行,只执行一次,用于给类进行初始化。
 
三、继承
1、继承概述
继承:提高了代码的复用性;让类与类之间产生了关系,有了这个关系,才有了多态的特性。
注意:千万不要为了获取其他类的功能简化代码而继承,必须类与类之间有所属关系才可以继承。
 
java语言中,java只支持单继承,不支持多继承。因为多继承容易带来安全隐患,当多个类中定义了相同功能,当功能内容不同时,子类对象不确定要运行哪一个,但是java保留这种机制,并用另一种体现形式来完成表示,多实现。
java支持多层继承,也就是一个继承体系,简单来说,就是查阅父类功能,创建子类对象使用功能。

2、继承的特点包括:子父类中变量的特点和子父类中函数的特点
a.子父类中变量的特点:
如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this;子类要访问父类中的同名变量,用super。
 
b.子父类中函数的特点:
当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容,如果父类的函数被覆盖一样,这种情况是很函数的另一个特性:重写,也叫做覆盖。(子类覆盖父类,必须要保证子类的权限大于等于父类权限,才可以覆盖,否则编译失败;静态只能覆盖静态。)

3、扩展知识:重载和重写的区别:
重载就是在类中可以创建多个方法,它们具有相同的方法名,但是参数类型和个数不一样,返回值类型可以相同也可以不相同。
 
重写是子类中的方法继承了父类中的方法,子父类方法要一模一样。如果需要父类中的方法,可以使用super关键字,该关键字引用了当前类的父类。子类函数的访问修饰权限不能小于父类的。
 
4、继承的一些知识点:
a.在对子类对象进行初始化时,父类的构造函数也会运行。那是因为子类的构造函数默认第一行有一条隐式的语句super();super()语句会访问父类中空参数的构造函数,而且子类中的所有构造函数默认第一行都是super()语句。
 
b.子类的所有构造函数,默认都会访问父类中空参数的构造函数,因为子类每一个构造函数内的第一行都有一句隐式super()语句,当父类中没有空参数的构造函数时,子类必须手动通过super语句的形式来指定要访问父类中的构造函数。当然,子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数,子类中至少会有一个构造函数会访问父类中的构造函数。(this(),super()写第一行,原因是为了先初始化)
 
5、关键字final
a.final可以修饰类,函数,变量;
 
b.被final修饰的类不可以被继承;为了避免被继承,被子类复写功能。
 
c.被final修饰的方法不可以被复写;
 
d.被final修饰的变量是一个常量,只能赋值一次,既可以修饰成员变量,又可以修饰局部变量。常量的修饰符书写规范:所有字母都大写,如果由多个单词组成,单词之间由_连接。
 
e.内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。
 
f.什么时候用final修饰呢?
在描述事物时,一些数据的出现值是固定的,那么这时为了增加阅读性,都给这些值起个名字,方便于阅读,而这个值不需要改变。就可以加上final修饰。

6、abstract抽象类
当多个类中出现相同功能,但是功能主体不同,这时可以进行向上抽取。这时,只抽取功能定义,而不抽取功能主体。
 
抽象类的特点:
a.抽象方法一定在抽象类中;
 
b.抽象方法和抽象类都必须被abstract关键字修饰;
 
c.抽象类不可以用new创建对象,因为调用抽象方法没有任何意义(功能无主体)
 
d.抽象类中的方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对象调用。如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。
 
e.抽象类中可以不定义抽象方法(作用是不让该类建立对象)
 
7、接口
接口:初期理解,可以认为是一个特殊的抽象类。当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。
注:class用于定义类,interface用于定义接口。

接口定义时,格式特点:
a.接口中常见定义,常量,抽象方法;
 
b.接口中的成员都有固定修饰符:
  常量: public static final
  方法: public  abstract                     
注意:接口中的成员都是public
 
接口的特点:
a.接口是对外暴露的规则;
 
b.接口是程序的功能扩展;
 
c.接口可以用来多实现;
 
d. 类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口;
 
e.接口与接口之间可以有继承关系;
 
接口知识点:
a.接口是不可以创建对象的,因为有抽象方法,需要被子类实现,子类对接口中的抽象方法全都覆盖后,子类才可以实例化。否则子类是一个抽象类;
 
b.接口可以被类多实现,也是对多继承不支持的转换形式,java支持多实现。接口间可以实现多继承。
 
接口与抽象类的区别:接口中都是抽象方法和常量,权限都是固定的。抽象类里可以存在非抽象方法。权限可以自己定。两者都需要子类去复写抽象方法才能实例化。

四、多态
1、多态:可以理解为事物存在的多种体现形态;     如:猫 x=new 猫();动物 x=new 猫();
 
2、多态的体现:父类的引用指向了自己的子类对象,父类的引用也可以接受自己的子类对象;
 
3、多态的前提: 必须是类与类之间有关系,要么继承,要么实现。还有一个前提是:存在覆盖。
 
4、多态的利弊: 利:多态的出现大大的提高了程序的扩展性 。   弊:提高了扩展性,但是只能使用父类的引用访问父类中的成员。
 
5、向上转型和向下转型:
向上转型:是指子类到父类的转换,会自动进行(隐式转换)类型转换,此时父类引用变量调用的方法是子类(覆盖或者继承)父类的方法,不是父类的方法。
向下转型:是指父类到子类的转型,必须进行(显式转换)强制转换,此时可以调用子类的特有方法。
注意:千万不能将父类对象转成子类类型,能转换的是父类引用指向自己的子类对象时,该引用可以被提升,也可以被强制转换。多态自始至终都是子类对象在变化。
 
6、多态的出现在代码中的特点:
a.在多态中,成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
 
在运行期:参阅对象所属的类中是否有调用的方法。
 
简单的总结:成员函数在多态调用时,编译看左边,运行看右边。
 
b.在多态中,成员变量的特点:无论编译和运行,都参考左边(引用型变量所属的类)。
 
c.在多态中:静态成员函数的特点:无论编译和运行,都参考左边。
 
五、Object类
Object:是类层次结构的根类。每个类使用Object作为超类,所有对象(包括数组)都实现这个类的方法。是所有对象的直接或者间接父类,该类中定义的肯定是所有对象都具备的功能。
 
Object中常用的方法:
a.比较当前对象与obj是否为同一对象,返回值:true/false
 
例:public boolean equals(Object obj)
 
b.返回当前对象的字符串表达式;
 
例:public String toString()
 
c、返回对象的Hash码,Hash码是标志对象的唯一值,Hash码相同的对象是同一对象;
 
public  native int  hashCode()
 
六、内部类与匿名内部类
内部类:将一个类定义在另一个类里面,对里面那个类就称为内部类(也叫内置类或嵌套类)

内部类的访问规则:
a.内部类可以直接访问外部类中的成员,包括私有成员;

b.外部类要访问内部类成员,必须建立内部类对象;
 
代码如下:

注:内部类可以直接访问外部类成员的原因:内部类中持有一个外部类的引用,格式:外部类名.this
 
访问格式:
 
a.当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中,直接建立内部类对象;
 
格式:外部类名.内部类名  变量名=外部类对象.内部类对象;
 
代码:  Outer.Inner in=new Outer().new Inner();
 
b.当内部类在成员位置上,就可以被成员修饰符所修饰;

private:将内部类在外部类中进行封装;
 
static: 内部类就具备static的特性,当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限。
 
c.在外部其他类中,如何直接访问静态内部类的非静态成员?
 
new outer.Inner.function();
 
d.在外部其他类中,如何直接访问static内部类的静态成员?
 
Outer.Inner.function();
 
注:当内部类中定义了静态成员,该内部类必须是static的;
    当外部类中的静态方法访问内部类时,内部类也必须是静态的。
    当内部类定义在局部时,不可以被成员修饰符修饰;可以直接访问外部类中的成员,因为还持有外部类中的引用,但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。而外部类要访问内部类中的成员必须要建立内部类对象。

匿名内部类:
a.匿名内部类其实就是内部类的简写格式;
 
b.定义匿名内部类的前提:内部类必须是继承一个类或者实现接口;
 
c.匿名内部类的格式:
 
new 父类或接口()
{
 
 定义子类的内容
 
}
 
d.其实匿名内部类就是一个匿名子类对象,而且这个对象有点“胖”,可以理解为带内容的对象;
 
e.匿名内部类中定义的方法最好不要超过3个;

 

七、扩展知识

Person p = new Person();
创建一个对象都在内存中做了什么事情?
a.先将硬盘上指定位置的Person.class文件加载进内存。
b.执行main方法时,在栈内存中开辟了main方法的空间(压栈-进栈),然后在main方法的栈区分配了一个变量p。
c.在堆内存中开辟一个实体空间,分配了一个内存首地址值。
d.在该实体空间中进行属性的空间分配,并进行了默认初始化。
e.对空间中的属性进行显示初始化。
f.进行实体的构造代码块初始化。
g.调用该实体对应的构造函数,进行构造函数初始化。
h.将首地址赋值给p ,p变量就引用了该实体。(指向了该对象)

-------android培训java培训、期待与您交流! ----------

0 0
原创粉丝点击