黑马程序员:Java基础之面向对象特性篇

来源:互联网 发布:社科院 工作 知乎 编辑:程序博客网 时间:2024/05/22 06:49

Java面向对象特性

一、类与对象

 

1.概念:     

       类:描述同一类对象的数据与行为,包含被创建对象的的属性及方法,把属性和方法封装起来就形成了一个类。特点:封装、继承、多态。

   对象:类的动态实例,具有对应类的属性和方法,即类的成员变量和成员方法。

 

2.类的声明及对象的创建:

       a.类的声明:类名+类的其他属性(访问权限+与其他类的关系)

[public] [abstract | final] class <classname>[extends superClassName]

                                                                     [implementsinterfaceNameList]

“[ ]”:表示可选项;”< >”:表示必选项;” | “:表示多选一。

 

b.类的结构:类声明类体{成员变量构造方法方法}

 

c.成员变量与局部变量:类中不属于任何一个方法的变量叫成员变量;属于方法体中的叫局部变量。成员变量在整个类中都有效,局部变量在其所在的方法内有效,当方法返回时,局部变量失效。

 

成员变量:[public|protected|private][static] [final] <type> <varibleName>

局部变量:[final]<type> <varibleName>

 

成员变量通过构造方法完成初始化:默认构造方法和自定义构造方法。

局部变量必须手动进行初始化,如果没有初始化,就报错。

 

成员变量与方法变量重名时,类的成员变量被隐藏,要想显示成员变量,则需要在变量前加关键字this.

 

d.成员方法[accessLevel] [static] [final] [abstract] [native][synchronized] <return_type> <name> ([argument_list]) [throws<exception_list>] {[block]}

accessLevel:包括publicprotectedprivate

static:指定该方法为静态方法。

final:指定该方法不能被重写。

abstract:指明该方法是抽象成员方法。

native:指明该方法是本地成员方法,即该方法用其他语言实现。

synchronized:控制多个并发线程对共享数据进行访问。

return_type:确定方法返回值类型,若没有返回值,用关键字void标识。

name:确定方法名。

argument_list:形式参数列表,方法可以为带参数和不带参数两种,对于无参数方法来说,即使方法体为空,方法名后的圆括号也不能省略;当存在多个参数时,各参数之间用逗号隔开。

throws <exception_list>:列出该方法抛出的一系列异常。

block:方法体,可以被省略,但是{}不能省。

成员方法的重载:方法名相同,但参数列表不同的方法是重载方法。方法的返回值类型和修饰符可相同,也可不同。

 

e.对象的创建

<className> <objectName>

对象的声明:在内存中为其分配一个引用空间,并置初值为null,表示不指向任何存储空间。声明对象以后用关键字new为对象分配存储空间,这个过程就是对象的实例化。

<className> <objectName> = new<SomeClass> ([argument_list]) ;

argument_list:指定构造方法的入口(对象初始化)参数,如果无参数,可省略。

 

f.对象的使用:对成员变量的访问,不提倡通过对象直接访问,应建立setget方法对变量进行读和写的操作。

对成员方法的调用,可用对象进行调用。

<objectReference> . methodName([argument_list]);

 

g.构造方法:用来对对象进行初始化,构造方法的名字必须与类名相同,且不能有返回值;用户不能直接调用构造方法,需通过关键字new自动调用它。可以理解为你创建对象才能用构造方法完成初始化,否则不能用构造方法。

Java为每个类提供了缺省构造方法(默认构造方法),不带参数且方法体为空,当在类中定义了显示构造方法进行初始化时,就不能再使用缺省构造方法,否则编译会失败。

构造方法也可以重载,重载的目的是使类的对象具有不同的初始值。一个类的若干个构造方法之间可以相互调用,需要使用this关键字。

 

h.this关键字:哪个对象调用thisthis就引用这个对象。

this.数据成员,访问当前对象的数据成员。

    this.成员方法,访问当前对象的成员方法。

       this(argument_list),重载构造方法时,用来引用同类的其他构造方法。注意必须第一行,因为初始化要先执行。

 

3.类的封装、继承与多态:

       a.类的封装:封装也叫数据隐藏,通过方法将对象的数据与实现细节保护起来,只保留一些对外接口,以便与外部发生关系。提高了数据的安全性,也方便用户使用。

访问权限:类和接口的权限只有publicdefault,类成员和构造方法可以是public,protected,default,private四种。(private<default<protected<public

 

同一个类中

同一个包中

不同包中的子类

任何场合

       private

yes

 

 

 

       default

yes

yes

 

 

       protected

yes

yes

yes

 

public

yes

yes

yes

yes

yes表示可以直接访问,空白表示不可以直接访问。

package:创建包:packagepk1 [.pk2 [.pk3] ] ; pk1指最外层的包,pk2pk3依次为更内层的包。package语句必须在程序中第一行。使用命令行,用指令

       javac -d 包的目标目录 someclass.java

在指定包中生成的相应的class文件。

      

       import:导入包中的类:import  pkg1[ . pkg2 [ . pkg3 ]] .<类名 |*> (巧用通配符“*”。)

 

       b.类的继承:一个类自动拥有另一个类的属性和方法时,那么这两个类之间就是继承关系,被继承的类叫父类(superclass),继承的类叫子类(subclass)

       [accessLevel] class <subClassName>extends <superClassName> {[类体]}

      

       单继承:Java不支持多重继承,只支持单继承,但是多重继承在现实世界中普遍存在,那么Java提供了interface接口机制,允许一个类实现多个接口,这样既避免了多重继承的复杂性,又达到了多重继承的效果。

      

super关键字:用来引用父类的成员,也可以在子类中使用super调用父类的构造方法,但是必须放在首行,否则子类将执行默认的缺省构造方法。使用方法与this一样,this在当前类中使用,而super在子类中使用。

 

方法重写:子类对从父类继承过来的方法进行改造。有一下几个规则:

*子类中重写的方法必须与父类被重写的方法具有一样的方法名,参数列表,和返回值类型。

*子类中的重写方法的权限不能缩小,必须大于或者等于父类被重写的方法。

*子类中重写的方法不能抛出新异常。

 

c. 类的多态:Java程序中相同名字的成员变量和方法可以表示不同的实现。

主要表现在方法重载,方法重写和变量覆盖上。

       方法重载是一种静态多态性,或称编译时多态。

       方法重写是一种动态多态性,或称运行时多态。

      

向下转型:父类引用指向自己的子类对象,事实上就是用子类对象来代替父类对象,通常是要使用子类对象中重写过的方法时用,注意,不能使用父类中没有的方法。

向上转型:又叫强制转型,通过instanceof判断父类引用的对象是否是该子类的另一个对象,或者是该子类的子类对象,才可以强制将父类引用转换。

 

       d.修饰符static

       static修饰符可用来修饰类中的成员变量和方法,被其修饰的成员变量叫静态变量或类变量,可直接通过类名进行访问,被其修饰的成员方法叫静态方法或类方法,可直接通过类名进行调用,无需建立对象访问。

       注意:类方法不能访问实例变量,只能访问类变量,原因是类方法比对象先加载到内存中,访问实例变量需通过对象,而此刻对象还没有被建立所以为非法。实例方法既可以访问类变量,也可以访问实例变量。

       static还可以修饰类中的代码块,此时该代码块被称为静态代码块。静态代码块在类中是随着类的加载而执行,并且只执行一次。它可以完成类变量的初始化且只会初始化一次。

       在类中除了静态代码块外还有非静态代码块,,用于对实例变量进行初始化,分为四步:

       *new运算符给实例变量分配空间时的默认初始化。

       *类定义中的显示初始化。

       *非静态代码块的初始化。

       *执行构造方法进行初始化。

注意:非静态代码块和静态代码块是在类中定义的,不是在方法中,且它们在类中的定义顺序可以是任意的。

 

       e.修饰符final:

       final修饰的类叫最终类,不能被继承,不能有子类,其成员方法也不会被重写。

       final修饰的方法叫最终方法,不能被重写。

 

       final修饰的成员变量和局部变量一定要赋值,否则编译错误。被final修饰的基本类型变量不能被重新赋值,被final修饰的引用型变量不能指向其他对象,但其对象的成员变量值可以被改变。

 

对于final修饰的实例变量,其明确初始化的位置有三处:一是定义时的显示初始化,二是非静态代码块,三是构造方法。

 

对于final修饰的类变量,其明确初始化位置有二处:一是定义时的显示初始化,二是静态代码块。

 

f.抽象类:<public> abstract class <className>

{abstract <returnType>methodName(param_list)}

 

抽象类只有声明或含有抽象方法或含有非抽象方法的类体。抽象方法同样只有声明,没有方法的可实现部分。

 

一个类继承抽象类,必须实现其所有的抽象方法,否则,该类也变成抽象类。

抽象类(父类)引用指向具体的子类对象,实现向下转型的多态,可执行不同子类的重写后的方法。

 

注意:finalabstract不能同时用来修饰类和方法。

         static不能修饰抽象方法。

抽象类中的访问权限不能设置成private

抽象类中可以定义构造方法,但是不可以用new来产生该抽象类的实例。

      

       g.接口interface接口的出现解决了用多实现的方式变向的解决了类不能多继承的问题。

       一个类可以实现多个接口,一个接口可以继承多个接口。

      

接口从本质上说也是一种抽象类,其成员变量默认被public static final修饰,其成员方法默认被public abstract修饰。所以接口中定义的都是常量;接口中有抽象方法,表示其也是抽象的,所以不能被final修饰;接口中的所有方法都是抽象的,所以方法不能被static修饰。

       当类同时继承父类并实现接口时,extends必须在implement

       一个类实现接口时,要将接口中的所有方法全部事项,否则该类就必须定义为抽象类。

       由于接口中的抽象方法访问权限为public,所以在类中实现后的非抽象方法访问权限必须是public

       通过接口类型的变量来引用具体对象时,只能访问接口中定义的方法,要想访问具体对象中的特有方法,则需要将接口类型引用强制转换成具体对象类型的引用,在转换之前用instanceof判断该引用所指向的对象是该类或接口类型及子类型时,就可强制转换了。所以多态是接口的好处之一。

 

       h.内部类:类中再定义个类,前者就是外部类,后者叫内部类,外部类的成员可以是变量,方法,也可以是一个类。所以可以将内部类当做一个成员来定义在外部类中,也可以将内部类定义在外部类的方法中。内部类可以有自己的成员变量和成员方法。

      

       非静态内部类:非静态内部类与外部类中其他成员一样,要依赖外部类的对象,要先创建外部类的对象之后才能创建内部类的对象。内部类的对象既可以在外部类的方法中被创建,也可以在外部类之外被创建。在外部类之外被创建的语法如下:

 

<外部类名> . <内部类名>引用变量 =<外部类对象引用>.new <内部类构造方法> ;

 

<外部类名> . <内部类名>引用变量 = new <外部类构造方法>.new <内部类构造方法> ;

 

       静态内部类:作为外部类的一个静态成员时,它依赖于该类,而不是该类的对象,所以在创建内部类时,不用先创建外部对象,同时,静态内部类不能访问外部类的非静态成员。在外部类之外被创建的语法如下:

 

<外部类名> . <内部类名>引用变量 =new<外部类名>. <内部类构造方法>;

 

注意:在非静态内部类中不能定义静态成员,原因是非静态的内部类创建对象时依赖外部类对象,若定义了静态成员,那么非静态在创建对象时就不需要依赖外部类对象从而出现矛盾。

           在静态内部类中可以定义静态成员。

 

内部类定义在成员方法中时,不可以被成员修饰符修饰;可以直接访问外部类成员,因为还持有外部类中的引用,但是不可以访问它所在的方法中的局部

变量,如想访问在需在变量前加final,因为非final的变量在方法执行完毕后会被销毁的,如果内部类中的一个方法使用了该变量(引用变量)做为自己的属性,并建立了自身的对象。当方法结束后内部类对象没有被销毁,并持有非final的引用变量的引用,而那个变量却被销毁,出现了矛盾。

 

       匿名内部类:匿名内部类其实就是内部类的简写格式,定义匿名内部类的前提是内部类必须继承一个父类或者实现一个接口,格式: new父类或接口(){定义子类的内容},其实匿名内部类就是一个匿名的子类对象,只不过这个对象带着内容,注意内部类中定义的方法最好不要超过3个。

 

       i.Object类:Java中每个类都是Object类的直接子类或者间接子类,所以每个类都可以使用Object类中的方法,下面介绍两种常用的方法:equals()方法和toString()方法。

      

       equals():用于判定某个指定对象的引用与当前对象的引用是否为同一个,所以只能比较引用类型变量,而“==”可以比较引用类型和基本类型。

注意:当equals比较的是String类对象时,比较的不再是引用,而是内容。

 

       toString():该方法是返回当前对象的类型和内存地址的信息,在调试时对确定对象的内部状态很有价值,为此在自定义类中都将该方法重写,以返回更有用的信息。