首页 > 代码库 > 02_Java面向对象(继承、封装、多态)

02_Java面向对象(继承、封装、多态)

1. 类的定义

     类定义包括类声明和类体两部分,类定义的语法格式如下:

     [修饰符] class 类名 [extends 父类名] [implements 类实现的接口列表] {类体}


2. 对象的创建与引用

     创建对象及访问对象成员

          1.声明对象 ,格式如下:

               类名  对象名表; 例如:Point   p1, p2;

          2.建立对象。实际上就是用Java提供的new关键字为对象分配存储空间。格式如下:

               引用变量名= new 构造方法();

               也可以在声明对象的同时建立对象 ,格式如下:类名 引用变量名 = new 构造方法() ;

          3.通过引用变量访问对象成员

               引用变量名.属性 

               引用变量名.方法名(实参表) 

     对象的初始化和构造方法

          在创建对象时,要给对象的属性成员分配内存空间,同时进行初始化。 

               [1]如果定义属性成员时没有指定初值,则系统自动指定初值.在定义属性成员时也可以指定初值.public class Point {private int x=10;    ……

               [2]指定初值的另一种办法是通过初始化块来设置对象的初值。

               //注意首先是按照属性定义的初值,然后是初始化块,

               [3]最后是构造方法:构造方法是给对相关设置初值的规范方法,构造方法是根据方法参数给对象属性赋不同的值.

                    构造方法的名称必须与类名同名; 

                    构造方法没有返回类型; 

                    通常一个类可提供多个构造方法,这些方法的参数不同。在创建对象时,系统自动调用参数匹配的构造方法为对象初始化

                    如果一个类未指定构造方法,则系统自动提供的无参构造方法,但如果自定义了构造方法,则系统不再提供无参构造方法。无参构造方法形式如下: public Person() { } , 所以自己最好还要默默的加入无参构造方法 


3. 变量的作用域

     变量的作用域也称变量的有效范围,它是程序的一个区域,变量在其作用域内可以通过它的名字来引用。作用域也决定系统什么时候为变量创建和清除内存。根据变量在程序声明的位置,可以将变量分为4类情形。

          [1]成员变量

                成员变量可添加修饰符,包括访问权限修饰符public、private、protected和非访问权限修饰符static、final、native等。

如果没有给对象属性赋初值,则对象属性的初始值由相应数据类型的默认值决定,如数值型数据的默认值为0,boolean的默认值为false,字符串的默认值为null。成员变量的作用域是在类的范围。

          [2]局部变量(自动变量) :  方法体中的局部变量 

               (1)在方法体内可以定义本方法所使用的变量,这种变量是局部变量,它的生存期与作用域是在本方法内。

               (2)方法体内定义变量时,变量前不能加修饰符。

               (3)局部变量在使用前必须明确赋值,因为它没有默认值,否则编译时会出错。

               //在语句块中定义的变量它只在语句块中有效;

          [3]方法参数:作用域是整个方法.

          [4]异常处理参数:catch跟随的异常处理块.


4. 类变量和静态方法

     用static修饰的属性是属于类的静态属性,相应的成员变量为类变量或静态变量.

          1.类变量的访问形式 

               在本类中直接访问:count 

               通过类名访问:User.count 

               通过类的一个对象访问,如:x1.count

               //这样用对象访问不是容易引起误会吗,淘汰吧.

          2.给类变量赋初值

               默认赋值即可,也可以用静态初始化代码块 static{count=100;}

               //静态初始化代码的执行是在main方法执行前完成。

     静态方法

          用 static修饰的方法称为静态方法,也叫类方法. 在static方法中只能处理类变量,也可访问其它static方法,但绝不能直接访问任何归属对象空间的变量或方法.


5. 理解this和super

     出现在类的实例方法或构造方法中,用来代表使用该方法的对象 .用this作前缀可访问当前对象的实例变量或成员方法.

          1. this.实例变量;

          2. this.成员方法(参数);

          3. this(参数),用来调用同类的另一构造方法.

     super和this差不多,都是一个引用指向自身和上一级父类罢了  


 6. 使用包组织类

     Java API简介: java中按包来组织类.包的组织采用分层结构,与文件系统中的目录的组织对应一致.通常将逻辑相关的类放在同一个包中.包将类的命名空间进行有效划分,同一包中不能有两个同名的类. Java系统提供的类库也成为Java API,他是系统提供的已实现的标准类的集合.

     建立包

           创建包就是在指定目录路径下创建一个 子文件夹 ,这个包中所有类的字节码文件将存放在该文件夹下.

           方法1:创建一个test子目录,将源程序文件存放到该目录,在该目录下利用javac编译源代码,或者在别处编译完程序后将字节码文件拷贝到该目录即可。 

           方法2:采用带路径指示的编译命令: 格式:javac –d  destpath  Point.java  

       编译器将自动在destpath指定的目录下建一个test子目录,并将产生的字节码文件保存到该子目录下 

典型用法是源程序放在当前目录下,用如下命令编译 javac –d . Point.java  编译后将在当前目录自动创建test子目录

     包的引用

          (1) 在引用类时使用包名作前缀例 :new java.util.Date() 

          (2) 用import语句加载需要使用的类。例:import java.util.Date; 然后在程序中可以直接通过类名创建对象, 如:new Date(); 

          (3) 用import语句加载整个包, 用“*”号代替类名位置。 它将加载包中的所有的类。例如:import java.util.*;


7. 继承

     Java继承的实现

          定义类时直接通过extends关键字指明要继承的父类.子类对象除了可以访问子类中直接定义的成员外,也可访问父类的所有非私有成员.能否直接访问父类私有成员则取决于访问权限设置.

     构造方法在类继承中的作用

          构造方法不能继承.由于子类对象要对来自父类的成员进行初始化,因此,在创建子类对象时除了执行子类的构造方法外,还需要调用父类的构造方法.具体遵循如下原则:

          (1) 当子类未定义构造方法时,创建对象时将无条件地调用父类的无参构造方法; 

          (2) 对于父类的含参数构造方法,子类可以在自己构造方法中使用关键字super来调用它,但super调用语句必须是子类构造方法中的第一个可执行语句; 

          (3) 子类在自己定义构造方法中如果没有用super明确调用父类的构造方法,则在创建对象时,将自动先执行父类的无参构造方法,然后再执行自己定义的构造方法。 

          所以在一个类的设计时如果有构造方法,最好提供一个无参构造方法.因此,系统类库中的类大多提供了无参构造方法,用户编程时最好也要养成此习惯.

     【注意】使用this查找匹配的方法时首先在本类查找,找不到时再到其父类和祖先类查找;使用 super 查找匹配方法时,首先到直接父类查找,如果不存在,则继续到其祖先类逐级往高层查找。


8. 多态性

     1.方法的重载

          方法调用的匹配处理原则是,首先按“精确匹配”原则去查找匹配方法,如果找不到,则按“自动类型转换匹配”原则去查找能匹配的方法。

          所谓“精确匹配”就是实参和形参类型完全一致。

          所谓“自动转换匹配”是指虽然实参和形参类型不同,但能将实参的数据按自动转换原则赋值给形参。     

     2.方法的覆盖

           方法名、参数列表、完全相同才会产生方法覆盖;返回类型通常也要一致,只有返回类型为引用类型时,允许子类方法的返回类型是父类方法返回类型的子类型。其他情形导致类型不一致时编译将指示错误。

          覆盖不能改变方法的静态与非静态属性。子类中不能将父类非静态方法定义为静态方法,反之也一样。 

          不允许子类方法的访问修饰符比父类有更多的限制。例如:子类不能将父类的public方法定义为protected方法。但可以将父类的private方法在子类中重新定义为public方法.通常将子类方法访问修饰符与父类保持一致.

          final方法不能被覆盖。

          [注意] 如果子类中定义了与父类同名的属性,在子类中将隐藏来自父类的同名属性变量. 对象执行方法时由实际对象的类型决定,而不是引用变量类型 ;

访问属性时则由引用类型决定,因为编译程序在分析程序时是基于类型来决定访问哪个属性变量 ;

静态成员的访问是基于引用类型,而不是对象类型.

     3.访问继承的成员

          得知通过子类对象赋值给父类的引用变量后,通过该引用变量去访问对象的成员时,访问的行为方法是子类对象的,而属性值确是父类的.其实就是编译系统是基于类型来决定的.

          是基于引用类型/实际对象?

          当子类和父类有相同成员时,通过子类引用访问的成员都是子类定义的,而通过父类引用变量操作子类对象时,只有实例方法存在覆盖关系,而对象属性,静态属性,静态方法均是父类定义的.

     4.几个特殊类

           Object类: 所有Java类的最终祖先,编译系统默认继承Object类,Object类包含了所有Java类的公共属性和方法,下面是四个常用方法.

               public boolean equals(Object obj) :该方法本意用于两个对象的“深度”比较,也就是比较两对象封装的数据是否相等;而比较运算符“==”在比较两对象变量时,只有当两个对象引用指向同一对象时才为真值。但在Object类中,equals方法是采用“==”运算进行比较;

               public String toString():该方法返回对象的字符串描述;

               public final Class getClass():返回对象的所属类;

               protected  void  finalize(): 该方法Java垃圾回收程序在删除对象前自动执行。

          Class类

          1.获取Class类型的对象

               Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。有以下3种方法可以获取Class的对象。

          方法1:调用Object类的getClass()方法。

          方法2:使用Class类的forName()方法。

          方法3:如果T是一个Java类型,那么T.class就代表了与该类型匹配的Class对象。例如,String.class代表字符串类型,int.class代表整数类型。

          2.Class类的常用方法

               java运行环境中提供了反射机制,这种机制允许程序中动态获取类的信息,以及动态调用对象的方法.            

               [1] static Class<?> forName(String className):返回给定串名相应的Class对象。

               [2] T newInstance():创建类的一个实例。

               [3] String getName():返回Class对象表示的类型(类、接口、数组或基类型)的完整路径名字符串。

               [4] Method[] getMethods():返回当前Class对象表示的类或接口的所有公有成员方法对象的数组。

进一步利用Method类提供的invoke方法可实现相应类的成员方法的调用。

     Object invoke(Object obj,Object[ ] args)

          其中,obj代表调用该方法的类实例对象,args代表存放方法参数的对象数组。

               Method getMethods(String name,Class…parameterType):返回指定方法名和参数类型的方法对象。

               Field[ ] getFields():返回当前Class对象表示的类或接口的所有可访问的公有域对象的数组。


9. 访问控制修饰符

     1.公共访问控制符public

          [1]作为类的修饰符,将类声明为公共类, 表明它可以被所有的其它类所访问和引用 

          [2]作为类的成员的访问修饰符,表明在其他类中可以无限制地访问该成员。 

          要真正做到类成员可以在任何地方访问,在进行类设计时必须同时满足两点:首先类被定义为public,其次,类的成员被定义为public。

     2.默认访问控制符

          没有给出访问控制符情形,该类只能被同一个包中的类访问和引用,不能被其他包中的类使用.

     3.私有访问控制符private

          用来声明类的私有成员,它提供了最高级的保护.用private修饰的域和方法只能被该类自身访问和修改,不能被任何其他类(包括该类的子类)来获取和引用.

          通常,出于系统设计的安全考虑,将类的成员属性定义为private保护起来,而类的成员方法public对外公开,这是类封装特性的一个体现.

     4.保护访问控制符protected

          用protected修饰的成员可以在三种类中所引用: 

               该类本身;与它在同一个包中的其它类;在其它包中的该类的子类。 spacer.gif


10. final修饰符的使用

     1.final作为类修饰符: 这种类成为最终类,特点是不允许继承.例如Api中的Math,String,Integer类都是final类.

     2.final修饰方法: 是功能和内部语句不能被更改的最终方法,在子类中不能再对父类的final方法重定义.所有private修饰的为私有方法和final类中的方法都默认为是final.

     //所有private都是final方法, 当然也可以手动加上final, final方法,final变量,private 方法. 这三种东西可以横向比较理解.

     3.final定义常量:只能赋值一次 例如 final double PI=3.14159;

     //带static的类常量只能在定义或静态代码块中赋值


11. 对象引用转换

     对象引用赋值转换: 允许将子类对象赋值给父类引用,父类表示的范围比较广,反之则不行.

     对象引用强制转换

          将父类引用赋值给子类变量时要进行强制转换,强制转换在编译时总是认可的,但运行时的情况取决于对象的值.如果父类对象引用指向的就是该子类的一个对象,则转换是成功的.否则会抛出异常.


02_Java面向对象(继承、封装、多态)